From 6d7af9133dd8eaab040c3c8de6629edabe0b4f4c Mon Sep 17 00:00:00 2001 From: syntrust Date: Fri, 5 Jan 2024 17:36:08 +0800 Subject: [PATCH 01/45] doc update --- README.md | 3 ++- ethstorage/miner/cli.go | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 786de31c..836d1052 100644 --- a/README.md +++ b/README.md @@ -81,9 +81,10 @@ The full list of options that you can use to configure an es-node are as follows |`--miner.enabled`|Storage mining enabled||| |`--miner.gas-price`|Gas price for mining transactions||| |`--miner.priority-gas-price`|Priority gas price for mining transactions||| +|`--miner.zk-prover-version value`|ZK prover version, 1: one proof per sample, 2: one proof for multiple samples|`2`|| |`--miner.threads-per-shard`|Number of threads per shard|`runtime.NumCPU() x 2`|| |`--miner.zk-working-dir`|Path to the snarkjs folder|`build/bin`|| -|`--miner.zkey`|zkey file name which should be put in the snarkjs folder|`blob_poseidon.zkey`|| +|`--miner.zkey`|zkey file name which should be put in the snarkjs folder|`blob_poseidon2.zkey`|| |`--miner.min-profit`|Minimum profit for mining transactions|`0`|| |`--network`|Predefined L1 network selection. Available networks: devnet||| |`--p2p.advertise.ip`|The IP address to advertise in Discv5, put into the ENR of the node. This may also be a hostname / domain name to resolve to an IP.||| diff --git a/ethstorage/miner/cli.go b/ethstorage/miner/cli.go index 0846acde..465219d0 100644 --- a/ethstorage/miner/cli.go +++ b/ethstorage/miner/cli.go @@ -65,7 +65,7 @@ func CLIFlags(envPrefix string) []cli.Flag { }, cli.Uint64Flag{ Name: ZKProverVersionFlagName, - Usage: "ZK prover version, 1: one proof per sample, 2: one proof for multiple samples. Default: 2", + Usage: "ZK prover version, 1: one proof per sample, 2: one proof for multiple samples", Value: DefaultConfig.ZKProverVersion, EnvVar: rollup.PrefixEnvVar(envPrefix, "ZK_PROVER_VERSION"), }, From bf75e6d843a6de76aff6e177cbb613f407395675 Mon Sep 17 00:00:00 2001 From: syntrust Date: Fri, 5 Jan 2024 19:27:54 +0800 Subject: [PATCH 02/45] introduce rapid --- ethstorage/prover/zk_prover.go | 94 +++++++++++++++------------------- go.mod | 5 ++ go.sum | 18 +++++++ 3 files changed, 64 insertions(+), 53 deletions(-) diff --git a/ethstorage/prover/zk_prover.go b/ethstorage/prover/zk_prover.go index 4f39d2a5..a9a9cdf7 100644 --- a/ethstorage/prover/zk_prover.go +++ b/ethstorage/prover/zk_prover.go @@ -21,6 +21,9 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" + "github.com/iden3/go-rapidsnark/prover" + "github.com/iden3/go-rapidsnark/witness/v2" + "github.com/iden3/go-rapidsnark/witness/wasmer" ) const ( @@ -125,58 +128,23 @@ func (p *ZKProver) GenerateZKProof(encodingKeys []common.Hash, sampleIdxs []uint EncodingKeyIn: encodingKeyModStr, XIn: xInStr, } - err = json.NewEncoder(file).Encode(inputObj) - if err != nil { - p.lg.Error("Write input file failed", "error", err) - return nil, nil, err - } p.lg.Debug("Generate zk proof", "input", inputObj) - - // 2. Generate witness - wtnsFile := filepath.Join(buildDir, wtnsName) - cmd := exec.Command("node", - filepath.Join(libDir, witnessGenerator), - filepath.Join(libDir, wasmName2), - inputFile, - wtnsFile, - ) - cmd.Dir = libDir - out, err := cmd.Output() + inputBytes, err := json.Marshal(inputObj) if err != nil { - p.lg.Error("Generate witness failed", "error", err, "cmd", cmd.String(), "output", string(out)) - return nil, nil, err - } - p.lg.Debug("Generate witness done") - - // 3. Generate proof - proofFile := filepath.Join(buildDir, proofName) - publicFile := filepath.Join(buildDir, publicName) - cmd = exec.Command("snarkjs", "groth16", "prove", - filepath.Join(libDir, p.zkeyFile), - wtnsFile, - proofFile, - publicFile, - ) - cmd.Dir = libDir - out, err = cmd.Output() - if err != nil { - p.lg.Error("Generate proof failed", "error", err, "cmd", cmd.String(), "output", string(out)) + p.lg.Error("Marshal input failed", "error", err) return nil, nil, err } - p.lg.Debug("Generate proof done") - - // 4. Read proof and masks - proof, err := readProof(proofFile) + zkeyBytes, err := os.ReadFile(filepath.Join(libDir, p.zkeyFile)) if err != nil { - p.lg.Error("Parse proof failed", "error", err) + p.lg.Error("Read zkey file failed", "error", err) return nil, nil, err } - masks, err := readMasks(publicFile) + wasmBytes, err := os.ReadFile(filepath.Join(libDir, witnessGenerator)) if err != nil { - p.lg.Error("Read mask failed", "error", err) + p.lg.Error("Read wasm file failed", "error", err) return nil, nil, err } - return proof, masks, nil + return prove(inputBytes, zkeyBytes, wasmBytes) } // Generate ZK Proof for the given encoding key and chunck index using snarkjs @@ -285,6 +253,33 @@ func (p *ZKProver) GenerateZKProofPerSample(encodingKey common.Hash, sampleIdx u return proof, mask, nil } +func prove(inputs, zkey, wasm []byte) ([]byte, []*big.Int, error) { + calc, err := witness.NewCalculator(wasm, + witness.WithWasmEngine(wasmer.NewCircom2WitnessCalculator)) + if err != nil { + return nil, nil, err + } + + parsedInputs, err := witness.ParseInputs(inputs) + if err != nil { + return nil, nil, err + } + + wtnsBytes, err := calc.CalculateWTNSBin(parsedInputs, true) + if err != nil { + return nil, nil, err + } + proof, publicInputs, err := prover.Groth16ProverRaw(zkey, wtnsBytes) + if err != nil { + return nil, nil, err + } + masks, err := readMasks(publicInputs) + if err != nil { + return nil, nil, err + } + return []byte(proof), masks, nil +} + func readProof(proofFile string) ([]byte, error) { dat, err := os.ReadFile(proofFile) if err != nil { @@ -322,19 +317,12 @@ func readProof(proofFile string) ([]byte, error) { return encoded, nil } -func readMasks(publicFile string) ([]*big.Int, error) { - var masks []*big.Int - f, err := os.Open(publicFile) - if err != nil { - return masks, err - } - defer f.Close() +func readMasks(publicInputs string) ([]*big.Int, error) { var output []string - var decoder = json.NewDecoder(f) - - if err = decoder.Decode(&output); err != nil { - return masks, err + if err := json.Unmarshal([]byte(publicInputs), &output); err != nil { + return nil, err } + var masks []*big.Int for _, v := range output { mask, ok := new(big.Int).SetString(v, 0) if !ok { diff --git a/go.mod b/go.mod index 6185b741..40b539f9 100644 --- a/go.mod +++ b/go.mod @@ -56,6 +56,9 @@ require ( github.com/hashicorp/golang-lru/arc/v2 v2.0.5 // indirect github.com/herumi/bls-eth-go-binary v1.28.1 // indirect github.com/huin/goupnp v1.3.0 // indirect + github.com/iden3/go-rapidsnark/types v0.0.2 // indirect + github.com/iden3/go-rapidsnark/witness/v2 v2.0.0 // indirect + github.com/iden3/wasmer-go v0.0.1 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/kilic/bls12-381 v0.1.1-0.20220929213557-ca162e8a70f4 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect @@ -103,6 +106,8 @@ require ( github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b // indirect github.com/hashicorp/go-multierror v1.1.1 github.com/hashicorp/golang-lru/v2 v2.0.5 + github.com/iden3/go-rapidsnark/prover v0.0.10 + github.com/iden3/go-rapidsnark/witness/wasmer v0.0.0-20230524142950-0986cf057d4e github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/ipfs/go-cid v0.4.1 // indirect github.com/ipfs/go-ds-leveldb v0.5.0 diff --git a/go.sum b/go.sum index 4d5db29c..72cac55a 100644 --- a/go.sum +++ b/go.sum @@ -88,6 +88,7 @@ github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 h1:aPEJyR4rPBvD github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593/go.mod h1:6hk1eMY/u5t+Cf18q5lFMUA1Rc+Sm5I6Ra1QuPyxXCo= github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= github.com/cockroachdb/redact v1.1.3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cockroachdb/sentry-go v0.6.1-cockroachdb.2/go.mod h1:8BT+cPK6xvFOcRlk0R8eg+OTkcqI6baNH4xAkpiYVvQ= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= @@ -192,6 +193,7 @@ github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclK github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= +github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= @@ -307,6 +309,16 @@ github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/iden3/go-rapidsnark/prover v0.0.10 h1:NvOfRPpex/k646UsqOcUy7a7uVl17t4ok9kWvpQg4+k= +github.com/iden3/go-rapidsnark/prover v0.0.10/go.mod h1:wgDsmKOGCuWGtgVtuW9ARWNguNr4NJAIyg2G7+uTax0= +github.com/iden3/go-rapidsnark/types v0.0.2 h1:CjJSrlbWchHzuMRdxSYrEh7n/akP+Z2PLNbwT5yBmQY= +github.com/iden3/go-rapidsnark/types v0.0.2/go.mod h1:ApgcaUxKIgSRA6fAeFxK7p+lgXXfG4oA2HN5DhFlfF4= +github.com/iden3/go-rapidsnark/witness/v2 v2.0.0 h1:mkY6VDfwKVJc83QGKmwVXY2LYepidPrFAxskrjr8UCs= +github.com/iden3/go-rapidsnark/witness/v2 v2.0.0/go.mod h1:3JRjqUfW1hgI9hzLDO0v8z/DUkR0ZUehhYLlnIfRxnA= +github.com/iden3/go-rapidsnark/witness/wasmer v0.0.0-20230524142950-0986cf057d4e h1:lqrevdLsG1k8ieaxgUQccf3unf73m3zmkHJ3oIdld90= +github.com/iden3/go-rapidsnark/witness/wasmer v0.0.0-20230524142950-0986cf057d4e/go.mod h1:WUtPVKXrhfZHJXavwId2+8J/fKMHQ92N0MZDxt8sfEA= +github.com/iden3/wasmer-go v0.0.1 h1:TZKh8Se8B/73PvWrcu+FTU9L1k5XYAmtFbioj7l0Uog= +github.com/iden3/wasmer-go v0.0.1/go.mod h1:ZnZBAO012M7o+Q1INXLRIxKQgEcH2FuwL0Iga8A4ufg= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -339,11 +351,14 @@ github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZl github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= github.com/kataras/golog v0.0.10/go.mod h1:yJ8YKCmyL+nWjERB90Qwn+bdyBZsaQwU3bTVFgkFIp8= github.com/kataras/iris/v12 v12.1.8/go.mod h1:LMYy4VlP67TQ3Zgriz8RE2h2kMZV2SgMYbq3UhfoFmE= @@ -461,6 +476,7 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= @@ -489,6 +505,7 @@ github.com/multiformats/go-multistream v0.5.0/go.mod h1:n6tMZiwiP2wUsR8DgfDWw1dy github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= @@ -622,6 +639,7 @@ github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= From bf7668b3521ca5d8841a04cb4d5a40e8d1153f5b Mon Sep 17 00:00:00 2001 From: syntrust Date: Mon, 8 Jan 2024 10:53:50 +0800 Subject: [PATCH 03/45] remove snarkjs --- Dockerfile | 10 +- Makefile | 2 +- ethstorage/miner/cli.go | 3 +- .../{snarkjs => snark_lib}/blob_poseidon.wasm | Bin .../blob_poseidon2.wasm | Bin .../blob_poseidon2_verification_key.json | 0 .../blob_poseidon_verification_key.json | 0 ethstorage/prover/snarkbuild/.gitignore | 2 - ethstorage/prover/snarkjs/generate_witness.js | 20 -- .../prover/snarkjs/witness_calculator.js | 337 ------------------ ethstorage/prover/zk_prover.go | 329 ++--------------- integration_tests/zk_prover_test.go | 108 +++++- run.sh | 8 +- 13 files changed, 136 insertions(+), 683 deletions(-) rename ethstorage/prover/{snarkjs => snark_lib}/blob_poseidon.wasm (100%) rename ethstorage/prover/{snarkjs => snark_lib}/blob_poseidon2.wasm (100%) rename ethstorage/prover/{snarkjs => snark_lib}/blob_poseidon2_verification_key.json (100%) rename ethstorage/prover/{snarkjs => snark_lib}/blob_poseidon_verification_key.json (100%) delete mode 100644 ethstorage/prover/snarkbuild/.gitignore delete mode 100644 ethstorage/prover/snarkjs/generate_witness.js delete mode 100644 ethstorage/prover/snarkjs/witness_calculator.js diff --git a/Dockerfile b/Dockerfile index c1eca067..8b60f18e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,19 +1,13 @@ # Build ES node in a stock Go builder container -FROM golang:1.20-alpine as builder - +FROM golang:1.21-alpine as builder RUN apk add --no-cache gcc musl-dev linux-headers make - -# build ADD . /es-node WORKDIR /es-node RUN make # Pull ES node into a second stage deploy alpine container -FROM node:16-alpine +FROM alpine:latest COPY --from=builder /es-node/build/ /es-node/build/ - -# For zk proof -RUN npm install -g snarkjs RUN apk add --no-cache curl grep # Entrypoint diff --git a/Makefile b/Makefile index cba46cbe..23923e68 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ LDFLAGSSTRING +=-X 'main.BuildTime=$(BUILDDATE)' LDFLAGS := -ldflags "$(LDFLAGSSTRING)" es-node: build - cp -r ethstorage/prover/snarkjs build/bin + cp -r ethstorage/prover/snark_lib build/bin mkdir -p build/bin/snarkbuild build: diff --git a/ethstorage/miner/cli.go b/ethstorage/miner/cli.go index 465219d0..de4ead4d 100644 --- a/ethstorage/miner/cli.go +++ b/ethstorage/miner/cli.go @@ -10,6 +10,7 @@ import ( "path/filepath" "github.com/ethstorage/go-ethstorage/ethstorage/flags/types" + "github.com/ethstorage/go-ethstorage/ethstorage/prover" "github.com/ethstorage/go-ethstorage/ethstorage/rollup" "github.com/urfave/cli" ) @@ -91,7 +92,7 @@ type CLIConfig struct { } func (c CLIConfig) Check() error { - info, err := os.Stat(filepath.Join(c.ZKWorkingDir, "snarkjs")) + info, err := os.Stat(filepath.Join(c.ZKWorkingDir, prover.SnarkLib)) if err != nil { if os.IsNotExist(err) || !info.IsDir() { return fmt.Errorf("snarkjs folder not found in ZKWorkingDir: %v", err) diff --git a/ethstorage/prover/snarkjs/blob_poseidon.wasm b/ethstorage/prover/snark_lib/blob_poseidon.wasm similarity index 100% rename from ethstorage/prover/snarkjs/blob_poseidon.wasm rename to ethstorage/prover/snark_lib/blob_poseidon.wasm diff --git a/ethstorage/prover/snarkjs/blob_poseidon2.wasm b/ethstorage/prover/snark_lib/blob_poseidon2.wasm similarity index 100% rename from ethstorage/prover/snarkjs/blob_poseidon2.wasm rename to ethstorage/prover/snark_lib/blob_poseidon2.wasm diff --git a/ethstorage/prover/snarkjs/blob_poseidon2_verification_key.json b/ethstorage/prover/snark_lib/blob_poseidon2_verification_key.json similarity index 100% rename from ethstorage/prover/snarkjs/blob_poseidon2_verification_key.json rename to ethstorage/prover/snark_lib/blob_poseidon2_verification_key.json diff --git a/ethstorage/prover/snarkjs/blob_poseidon_verification_key.json b/ethstorage/prover/snark_lib/blob_poseidon_verification_key.json similarity index 100% rename from ethstorage/prover/snarkjs/blob_poseidon_verification_key.json rename to ethstorage/prover/snark_lib/blob_poseidon_verification_key.json diff --git a/ethstorage/prover/snarkbuild/.gitignore b/ethstorage/prover/snarkbuild/.gitignore deleted file mode 100644 index c96a04f0..00000000 --- a/ethstorage/prover/snarkbuild/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore \ No newline at end of file diff --git a/ethstorage/prover/snarkjs/generate_witness.js b/ethstorage/prover/snarkjs/generate_witness.js deleted file mode 100644 index eabb86e5..00000000 --- a/ethstorage/prover/snarkjs/generate_witness.js +++ /dev/null @@ -1,20 +0,0 @@ -const wc = require("./witness_calculator.js"); -const { readFileSync, writeFile } = require("fs"); - -if (process.argv.length != 5) { - console.log("Usage: node generate_witness.js "); -} else { - const input = JSON.parse(readFileSync(process.argv[3], "utf8")); - - const buffer = readFileSync(process.argv[2]); - wc(buffer).then(async witnessCalculator => { - // const w= await witnessCalculator.calculateWitness(input,0); - // for (let i=0; i< w.length; i++){ - // console.log(w[i]); - // } - const buff= await witnessCalculator.calculateWTNSBin(input,0); - writeFile(process.argv[4], buff, function(err) { - if (err) throw err; - }); - }); -} diff --git a/ethstorage/prover/snarkjs/witness_calculator.js b/ethstorage/prover/snarkjs/witness_calculator.js deleted file mode 100644 index 20e6e20a..00000000 --- a/ethstorage/prover/snarkjs/witness_calculator.js +++ /dev/null @@ -1,337 +0,0 @@ -module.exports = async function builder(code, options) { - - options = options || {}; - - let wasmModule; - try { - wasmModule = await WebAssembly.compile(code); - } catch (err) { - console.log(err); - console.log("\nTry to run circom --c in order to generate c++ code instead\n"); - throw new Error(err); - } - - let wc; - - let errStr = ""; - let msgStr = ""; - - const instance = await WebAssembly.instantiate(wasmModule, { - runtime: { - exceptionHandler : function(code) { - let err; - if (code == 1) { - err = "Signal not found.\n"; - } else if (code == 2) { - err = "Too many signals set.\n"; - } else if (code == 3) { - err = "Signal already set.\n"; - } else if (code == 4) { - err = "Assert Failed.\n"; - } else if (code == 5) { - err = "Not enough memory.\n"; - } else if (code == 6) { - err = "Input signal array access exceeds the size.\n"; - } else { - err = "Unknown error.\n"; - } - throw new Error(err + errStr); - }, - printErrorMessage : function() { - errStr += getMessage() + "\n"; - // console.error(getMessage()); - }, - writeBufferMessage : function() { - const msg = getMessage(); - // Any calls to `log()` will always end with a `\n`, so that's when we print and reset - if (msg === "\n") { - console.log(msgStr); - msgStr = ""; - } else { - // If we've buffered other content, put a space in between the items - if (msgStr !== "") { - msgStr += " " - } - // Then append the message to the message we are creating - msgStr += msg; - } - }, - showSharedRWMemory : function() { - printSharedRWMemory (); - } - - } - }); - - const sanityCheck = - options -// options && -// ( -// options.sanityCheck || -// options.logGetSignal || -// options.logSetSignal || -// options.logStartComponent || -// options.logFinishComponent -// ); - - - wc = new WitnessCalculator(instance, sanityCheck); - return wc; - - function getMessage() { - var message = ""; - var c = instance.exports.getMessageChar(); - while ( c != 0 ) { - message += String.fromCharCode(c); - c = instance.exports.getMessageChar(); - } - return message; - } - - function printSharedRWMemory () { - const shared_rw_memory_size = instance.exports.getFieldNumLen32(); - const arr = new Uint32Array(shared_rw_memory_size); - for (let j=0; j { - const h = fnvHash(k); - const hMSB = parseInt(h.slice(0,8), 16); - const hLSB = parseInt(h.slice(8,16), 16); - const fArr = flatArray(input[k]); - let signalSize = this.instance.exports.getInputSignalSize(hMSB, hLSB); - if (signalSize < 0){ - throw new Error(`Signal ${k} not found\n`); - } - if (fArr.length < signalSize) { - throw new Error(`Not enough values for input signal ${k}\n`); - } - if (fArr.length > signalSize) { - throw new Error(`Too many values for input signal ${k}\n`); - } - for (let i=0; i0) { - res.unshift(0); - i--; - } - } - return res; -} - -function fromArray32(arr) { //returns a BigInt - var res = BigInt(0); - const radix = BigInt(0x100000000); - for (let i = 0; i Date: Mon, 8 Jan 2024 12:39:13 +0800 Subject: [PATCH 04/45] init zk prover --- .github/workflows/publish.yml | 3 +- Makefile | 1 - ethstorage/miner/cli.go | 6 +- ethstorage/prover/kzg_poseidon_prover.go | 51 ++++++++++-- ethstorage/prover/zk_prover.go | 98 +++++++++--------------- 5 files changed, 83 insertions(+), 76 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index a5b568b2..e644a29d 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -24,8 +24,7 @@ jobs: - name: Create package run: | - mkdir -p ${{ env.BIN_DIR }}/snarkbuild - cp -r ethstorage/prover/snarkjs ${{ env.BIN_DIR }} + cp -r ethstorage/prover/snark_lib ${{ env.BIN_DIR }} cp run.sh ${{ env.BUILD_DIR }} - name: Build diff --git a/Makefile b/Makefile index 23923e68..ed05c858 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,6 @@ LDFLAGS := -ldflags "$(LDFLAGSSTRING)" es-node: build cp -r ethstorage/prover/snark_lib build/bin - mkdir -p build/bin/snarkbuild build: env GO111MODULE=on GOOS=$(TARGETOS) GOARCH=$(TARGETARCH) go build -v $(LDFLAGS) -o build/bin/es-node ./cmd/es-node/ diff --git a/ethstorage/miner/cli.go b/ethstorage/miner/cli.go index de4ead4d..4faaa952 100644 --- a/ethstorage/miner/cli.go +++ b/ethstorage/miner/cli.go @@ -54,13 +54,13 @@ func CLIFlags(envPrefix string) []cli.Flag { }, cli.StringFlag{ Name: ZKeyFileNameFlagName, - Usage: "zkey file name which should be put in the snarkjs folder", + Usage: "zkey file name which should be put in the snark_lib folder", Value: DefaultConfig.ZKeyFileName, EnvVar: rollup.PrefixEnvVar(envPrefix, "ZKEY_FILE"), }, cli.StringFlag{ Name: ZKWorkingDirFlagName, - Usage: "Path to the snarkjs folder", + Usage: "Path to the snark_lib folder", Value: DefaultConfig.ZKWorkingDir, EnvVar: rollup.PrefixEnvVar(envPrefix, "ZK_WORKING_DIR"), }, @@ -95,7 +95,7 @@ func (c CLIConfig) Check() error { info, err := os.Stat(filepath.Join(c.ZKWorkingDir, prover.SnarkLib)) if err != nil { if os.IsNotExist(err) || !info.IsDir() { - return fmt.Errorf("snarkjs folder not found in ZKWorkingDir: %v", err) + return fmt.Errorf("%s folder not found in ZKWorkingDir: %v", prover.SnarkLib, err) } } return nil diff --git a/ethstorage/prover/kzg_poseidon_prover.go b/ethstorage/prover/kzg_poseidon_prover.go index a8fc1c0f..b5a20946 100644 --- a/ethstorage/prover/kzg_poseidon_prover.go +++ b/ethstorage/prover/kzg_poseidon_prover.go @@ -4,27 +4,56 @@ package prover import ( + "errors" "fmt" "math/big" + "os" + "path/filepath" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/log" ) +const ( + SnarkLib = "snark_lib" + WasmName = "blob_poseidon.wasm" + Wasm2Name = "blob_poseidon2.wasm" +) + type KZGPoseidonProver struct { - dir, zkey string - version uint64 - lg log.Logger + version uint64 + libDir string + zkey string + lg log.Logger } // Prover that can be used directly by miner to prove both KZG and Poseidon hash // workingDir specifies the working directory of the command relative to the caller. -// zkeyFileName specifies the zkey file name used by snarkjs to generate snark proof +// zkeyFileName specifies the zkey file name to generate snark proof // returns a prover that can generate a combined KZG + zk proof func NewKZGPoseidonProver(workingDir, zkeyFileName string, version uint64, lg log.Logger) KZGPoseidonProver { + libDir := filepath.Join(workingDir, SnarkLib) + if _, err := os.Stat(libDir); errors.Is(err, os.ErrNotExist) { + lg.Crit("Init ZK prover failed", "error", "snark lib does not exist", "dir", libDir) + } + zkeyFile := filepath.Join(libDir, zkeyFileName) + if _, err := os.Stat(zkeyFile); errors.Is(err, os.ErrNotExist) { + lg.Crit("Init ZK prover failed", "error", "zkey does not exist", "dir", zkeyFile) + } + var wasmFile string + if version == 2 { + wasmFile = filepath.Join(libDir, wasm2Name) + } else if version == 1 { + wasmFile = filepath.Join(libDir, wasmName) + } else { + lg.Crit("Init ZK prover failed", "error", "invalid version", "version", version) + } + if _, err := os.Stat(zkeyFile); errors.Is(err, os.ErrNotExist) { + lg.Crit("Init ZK prover failed", "error", "wasm does not exist", "dir", wasmFile) + } return KZGPoseidonProver{ - dir: workingDir, version: version, + libDir: libDir, zkey: zkeyFileName, lg: lg, } @@ -49,8 +78,12 @@ func (p *KZGPoseidonProver) GetStorageProof(data [][]byte, encodingKeys []common var zkProofs [][]byte var masks []*big.Int if p.version == 1 { + prvr, err := NewZKProver(p.libDir, p.zkey, wasmName, p.lg) + if err != nil { + return nil, nil, nil, err + } for i, encodingKey := range encodingKeys { - zkProof, mask, err := NewZKProver(p.dir, p.zkey, p.lg).GenerateZKProofPerSample(encodingKey, sampleIdxInKv[i]) + zkProof, mask, err := prvr.GenerateZKProofPerSample(encodingKey, sampleIdxInKv[i]) if err != nil { return nil, nil, nil, err } @@ -58,7 +91,11 @@ func (p *KZGPoseidonProver) GetStorageProof(data [][]byte, encodingKeys []common masks = append(masks, mask) } } else if p.version == 2 { - zkProof, msks, err := NewZKProver(p.dir, p.zkey, p.lg).GenerateZKProof(encodingKeys, sampleIdxInKv) + prvr, err := NewZKProver(p.libDir, p.zkey, wasm2Name, p.lg) + if err != nil { + return nil, nil, nil, err + } + zkProof, msks, err := prvr.GenerateZKProof(encodingKeys, sampleIdxInKv) if err != nil { return nil, nil, nil, err } diff --git a/ethstorage/prover/zk_prover.go b/ethstorage/prover/zk_prover.go index b6e78b07..b181dabc 100644 --- a/ethstorage/prover/zk_prover.go +++ b/ethstorage/prover/zk_prover.go @@ -5,7 +5,6 @@ package prover import ( "encoding/json" - "errors" "fmt" "math/big" "os" @@ -22,44 +21,35 @@ import ( "github.com/iden3/go-rapidsnark/witness/wasmer" ) -const ( - SnarkLib = "snark_lib" - wasmName = "blob_poseidon.wasm" - wasm2Name = "blob_poseidon2.wasm" -) - type ZKProver struct { - dir, zkeyFile string - lg log.Logger - cleanup bool -} - -func NewZKProver(workingDir, zkeyFile string, lg log.Logger) *ZKProver { - return newZKProver(workingDir, zkeyFile, true, lg) + calc witness.Calculator + zkey []byte + lg log.Logger } -func NewZKProverInternal(workingDir, zkeyFile string, lg log.Logger) *ZKProver { - return newZKProver(workingDir, zkeyFile, false, lg) -} - -func newZKProver(workingDir, zkeyFile string, cleanup bool, lg log.Logger) *ZKProver { - path := workingDir - if path == "" { - path, _ = filepath.Abs("./") +func NewZKProver(libDir, zkeyName, wasmName string, lg log.Logger) (*ZKProver, error) { + wasmBytes, err := os.ReadFile(filepath.Join(libDir, wasmName)) + if err != nil { + lg.Error("Read wasm file failed", "error", err) + return nil, err } - libDir := filepath.Join(path, SnarkLib) - if _, err := os.Stat(libDir); errors.Is(err, os.ErrNotExist) { - lg.Crit("Init ZK prover failed", "error", "snark lib does not exist", "dir", libDir) + calc, err := witness.NewCalculator(wasmBytes, witness.WithWasmEngine(wasmer.NewCircom2WitnessCalculator)) + if err != nil { + return nil, err } - return &ZKProver{ - dir: path, - zkeyFile: zkeyFile, - cleanup: cleanup, - lg: lg, + zkey, err := os.ReadFile(filepath.Join(libDir, zkeyName)) + if err != nil { + lg.Error("Read zkey file failed", "error", err) + return nil, err } + return &ZKProver{ + zkey: zkey, + calc: calc, + lg: lg, + }, nil } -// Generate ZK Proof for the given encoding keys and chunck indexes using snarkjs +// Generate ZK Proof for the given encoding keys and chunck indexes func (p *ZKProver) GenerateZKProof(encodingKeys []common.Hash, sampleIdxs []uint64) ([]byte, []*big.Int, error) { for i, idx := range sampleIdxs { p.lg.Debug("Generate zk proof", "encodingKey", encodingKeys[i], "sampleIdx", sampleIdxs[i]) @@ -94,29 +84,30 @@ func (p *ZKProver) GenerateZKProof(encodingKeys []common.Hash, sampleIdxs []uint p.lg.Error("Marshal input failed", "error", err) return nil, nil, err } - libDir := filepath.Join(p.dir, SnarkLib) - zkeyBytes, err := os.ReadFile(filepath.Join(libDir, p.zkeyFile)) + parsedInputs, err := witness.ParseInputs(inputBytes) if err != nil { - p.lg.Error("Read zkey file failed", "error", err) + p.lg.Error("Parse input failed", "error", err) return nil, nil, err } - wasmBytes, err := os.ReadFile(filepath.Join(libDir, wasm2Name)) + wtnsBytes, err := p.calc.CalculateWTNSBin(parsedInputs, true) if err != nil { - p.lg.Error("Read wasm file failed", "error", err) + p.lg.Error("Calculate witness failed", "error", err) return nil, nil, err } - proof, publicInputs, err := prove(inputBytes, zkeyBytes, wasmBytes) + proof, publicInputs, err := prover.Groth16ProverRaw(p.zkey, wtnsBytes) if err != nil { + p.lg.Error("Prove failed", "error", err) return nil, nil, err } masks, err := readMasks(publicInputs) if err != nil { + p.lg.Error("Read masks failed", "error", err) return nil, nil, err } return []byte(proof), masks, nil } -// Generate ZK Proof for the given encoding key and chunck index using snarkjs +// Generate ZK Proof for the given encoding key and chunck index func (p *ZKProver) GenerateZKProofPerSample(encodingKey common.Hash, sampleIdx uint64) ([]byte, *big.Int, error) { p.lg.Debug("Generate zk proof", "encodingKey", encodingKey.Hex(), "sampleIdx", sampleIdx) if int(sampleIdx) >= eth.FieldElementsPerBlob { @@ -138,26 +129,25 @@ func (p *ZKProver) GenerateZKProofPerSample(encodingKey common.Hash, sampleIdx u EncodingKeyIn: hexutil.Encode(encodingKeyMod.Bytes()), XIn: xIn.String(), } - p.lg.Debug("Generate zk proof", "input", inputObj) inputBytes, err := json.Marshal(inputObj) if err != nil { p.lg.Error("Marshal input failed", "error", err) return nil, nil, err } - libDir := filepath.Join(p.dir, SnarkLib) - zkeyBytes, err := os.ReadFile(filepath.Join(libDir, p.zkeyFile)) + parsedInputs, err := witness.ParseInputs(inputBytes) if err != nil { - p.lg.Error("Read zkey file failed", "error", err) + p.lg.Error("Parse input failed", "error", err) return nil, nil, err } - wasmBytes, err := os.ReadFile(filepath.Join(libDir, wasmName)) + wtnsBytes, err := p.calc.CalculateWTNSBin(parsedInputs, true) if err != nil { - p.lg.Error("Read wasm file failed", "error", err) + p.lg.Error("Calculate witness failed", "error", err) return nil, nil, err } - proof, publicInputs, err := prove(inputBytes, zkeyBytes, wasmBytes) + proof, publicInputs, err := prover.Groth16ProverRaw(p.zkey, wtnsBytes) if err != nil { + p.lg.Error("Prove failed", "error", err) return nil, nil, err } mask, err := readMask(publicInputs) @@ -167,23 +157,6 @@ func (p *ZKProver) GenerateZKProofPerSample(encodingKey common.Hash, sampleIdx u return []byte(proof), mask, nil } -func prove(inputs, zkey, wasm []byte) (string, string, error) { - calc, err := witness.NewCalculator(wasm, - witness.WithWasmEngine(wasmer.NewCircom2WitnessCalculator)) - if err != nil { - return "", "", err - } - parsedInputs, err := witness.ParseInputs(inputs) - if err != nil { - return "", "", err - } - wtnsBytes, err := calc.CalculateWTNSBin(parsedInputs, true) - if err != nil { - return "", "", err - } - return prover.Groth16ProverRaw(zkey, wtnsBytes) -} - func readMasks(publicInputs string) ([]*big.Int, error) { var output []string if err := json.Unmarshal([]byte(publicInputs), &output); err != nil { @@ -222,7 +195,6 @@ func readMask(publicFile string) (*big.Int, error) { return mask, nil } -// input structure used by snarkjs type InputPairV2 struct { EncodingKeyIn []string `json:"encodingKeyIn"` XIn []string `json:"xIn"` From 51fd15f79721dbeb2ea965fe4a08884f8208617d Mon Sep 17 00:00:00 2001 From: syntrust Date: Mon, 8 Jan 2024 19:37:26 +0800 Subject: [PATCH 05/45] fix tests --- ethstorage/prover/kzg_poseidon_prover.go | 9 +- ethstorage/prover/zk_prover.go | 232 ++++++++++++++++++++--- go.mod | 2 +- go.sum | 2 + integration_tests/node_mine_test.go | 4 +- integration_tests/zk_prover2_test.go | 61 +++--- integration_tests/zk_prover_test.go | 171 ++--------------- 7 files changed, 248 insertions(+), 233 deletions(-) diff --git a/ethstorage/prover/kzg_poseidon_prover.go b/ethstorage/prover/kzg_poseidon_prover.go index b5a20946..7d63db23 100644 --- a/ethstorage/prover/kzg_poseidon_prover.go +++ b/ethstorage/prover/kzg_poseidon_prover.go @@ -32,6 +32,7 @@ type KZGPoseidonProver struct { // zkeyFileName specifies the zkey file name to generate snark proof // returns a prover that can generate a combined KZG + zk proof func NewKZGPoseidonProver(workingDir, zkeyFileName string, version uint64, lg log.Logger) KZGPoseidonProver { + // check dependencies when es-node starts libDir := filepath.Join(workingDir, SnarkLib) if _, err := os.Stat(libDir); errors.Is(err, os.ErrNotExist) { lg.Crit("Init ZK prover failed", "error", "snark lib does not exist", "dir", libDir) @@ -42,9 +43,9 @@ func NewKZGPoseidonProver(workingDir, zkeyFileName string, version uint64, lg lo } var wasmFile string if version == 2 { - wasmFile = filepath.Join(libDir, wasm2Name) + wasmFile = filepath.Join(libDir, Wasm2Name) } else if version == 1 { - wasmFile = filepath.Join(libDir, wasmName) + wasmFile = filepath.Join(libDir, WasmName) } else { lg.Crit("Init ZK prover failed", "error", "invalid version", "version", version) } @@ -78,7 +79,7 @@ func (p *KZGPoseidonProver) GetStorageProof(data [][]byte, encodingKeys []common var zkProofs [][]byte var masks []*big.Int if p.version == 1 { - prvr, err := NewZKProver(p.libDir, p.zkey, wasmName, p.lg) + prvr, err := NewZKProver(p.libDir, p.zkey, WasmName, p.lg) if err != nil { return nil, nil, nil, err } @@ -91,7 +92,7 @@ func (p *KZGPoseidonProver) GetStorageProof(data [][]byte, encodingKeys []common masks = append(masks, mask) } } else if p.version == 2 { - prvr, err := NewZKProver(p.libDir, p.zkey, wasm2Name, p.lg) + prvr, err := NewZKProver(p.libDir, p.zkey, Wasm2Name, p.lg) if err != nil { return nil, nil, nil, err } diff --git a/ethstorage/prover/zk_prover.go b/ethstorage/prover/zk_prover.go index b181dabc..14ce199f 100644 --- a/ethstorage/prover/zk_prover.go +++ b/ethstorage/prover/zk_prover.go @@ -13,10 +13,12 @@ import ( "github.com/consensys/gnark-crypto/ecc/bn254/fr" "github.com/crate-crypto/go-proto-danksharding-crypto/eth" + "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/log" "github.com/iden3/go-rapidsnark/prover" + "github.com/iden3/go-rapidsnark/types" "github.com/iden3/go-rapidsnark/witness/v2" "github.com/iden3/go-rapidsnark/witness/wasmer" ) @@ -49,7 +51,7 @@ func NewZKProver(libDir, zkeyName, wasmName string, lg log.Logger) (*ZKProver, e }, nil } -// Generate ZK Proof for the given encoding keys and chunck indexes +// Generate ZK Proof for the given encoding keys and sample indexes func (p *ZKProver) GenerateZKProof(encodingKeys []common.Hash, sampleIdxs []uint64) ([]byte, []*big.Int, error) { for i, idx := range sampleIdxs { p.lg.Debug("Generate zk proof", "encodingKey", encodingKeys[i], "sampleIdx", sampleIdxs[i]) @@ -63,6 +65,35 @@ func (p *ZKProver) GenerateZKProof(encodingKeys []common.Hash, sampleIdxs []uint p.lg.Info("Generate zk proof done", "sampleIdx", sampleIdxs, "took(sec)", dur.Seconds()) }(start) + parsedInputs, err := p.GenerateInputs(encodingKeys, sampleIdxs) + if err != nil { + p.lg.Error("Generate inputs failed", "error", err) + return nil, nil, err + } + wtnsBytes, err := p.calc.CalculateWTNSBin(parsedInputs, true) + if err != nil { + p.lg.Error("Calculate witness failed", "error", err) + return nil, nil, err + } + proofRaw, publicInputs, err := prover.Groth16ProverRaw(p.zkey, wtnsBytes) + if err != nil { + p.lg.Error("Prove failed", "error", err) + return nil, nil, err + } + proof, err := readProof(proofRaw) + if err != nil { + p.lg.Error("Read proof failed", "error", err) + return nil, nil, err + } + p.lg.Debug("Proof generated", "proof", proof) + masks, err := readMasks(publicInputs) + if err != nil { + p.lg.Error("Read masks failed", "error", err) + return nil, nil, err + } + return proof, masks, nil +} +func (p *ZKProver) GenerateInputs(encodingKeys []common.Hash, sampleIdxs []uint64) (map[string]interface{}, error) { var encodingKeyModStr, xInStr []string for i, sampleIdx := range sampleIdxs { var b fr.Element @@ -82,32 +113,17 @@ func (p *ZKProver) GenerateZKProof(encodingKeys []common.Hash, sampleIdxs []uint inputBytes, err := json.Marshal(inputObj) if err != nil { p.lg.Error("Marshal input failed", "error", err) - return nil, nil, err + return nil, err } parsedInputs, err := witness.ParseInputs(inputBytes) if err != nil { p.lg.Error("Parse input failed", "error", err) - return nil, nil, err - } - wtnsBytes, err := p.calc.CalculateWTNSBin(parsedInputs, true) - if err != nil { - p.lg.Error("Calculate witness failed", "error", err) - return nil, nil, err - } - proof, publicInputs, err := prover.Groth16ProverRaw(p.zkey, wtnsBytes) - if err != nil { - p.lg.Error("Prove failed", "error", err) - return nil, nil, err - } - masks, err := readMasks(publicInputs) - if err != nil { - p.lg.Error("Read masks failed", "error", err) - return nil, nil, err + return nil, err } - return []byte(proof), masks, nil + return parsedInputs, nil } -// Generate ZK Proof for the given encoding key and chunck index +// Generate ZK Proof for the given encoding key and sample index func (p *ZKProver) GenerateZKProofPerSample(encodingKey common.Hash, sampleIdx uint64) ([]byte, *big.Int, error) { p.lg.Debug("Generate zk proof", "encodingKey", encodingKey.Hex(), "sampleIdx", sampleIdx) if int(sampleIdx) >= eth.FieldElementsPerBlob { @@ -145,16 +161,54 @@ func (p *ZKProver) GenerateZKProofPerSample(encodingKey common.Hash, sampleIdx u p.lg.Error("Calculate witness failed", "error", err) return nil, nil, err } - proof, publicInputs, err := prover.Groth16ProverRaw(p.zkey, wtnsBytes) + proofRaw, publicInputs, err := prover.Groth16ProverRaw(p.zkey, wtnsBytes) if err != nil { p.lg.Error("Prove failed", "error", err) return nil, nil, err } + proof, err := readProof(proofRaw) + if err != nil { + p.lg.Error("Read proof failed", "error", err) + return nil, nil, err + } mask, err := readMask(publicInputs) if err != nil { return nil, nil, err } - return []byte(proof), mask, nil + p.lg.Debug("Generate zk proof", "mask", mask) + return proof, mask, nil +} + +func readProof(proofRaw string) ([]byte, error) { + var piOut = types.ProofData{} + if err := json.Unmarshal([]byte(proofRaw), &piOut); err != nil { + return nil, err + } + u2, _ := abi.NewType("uint256[2]", "", nil) + u22, _ := abi.NewType("uint256[2][2]", "", nil) + args := abi.Arguments{ + {Type: u2}, + {Type: u22}, + {Type: u2}, + } + a, err := toG1Point(piOut.A[:2]) + if err != nil { + return nil, err + } + b, err := toG2Point(piOut.B[0:2]) + if err != nil { + return nil, err + } + c, err := toG1Point(piOut.C[0:2]) + if err != nil { + return nil, err + } + values := []interface{}{[]*big.Int{a.X, a.Y}, [][]*big.Int{b.X[:], b.Y[:]}, []*big.Int{c.X, c.Y}} + packed, err := args.Pack(values...) + if err != nil { + return nil, fmt.Errorf("%v, values: %v", err, values) + } + return packed, nil } func readMasks(publicInputs string) ([]*big.Int, error) { @@ -173,16 +227,9 @@ func readMasks(publicInputs string) ([]*big.Int, error) { return masks, nil } -func readMask(publicFile string) (*big.Int, error) { - f, err := os.Open(publicFile) - if err != nil { - return nil, err - } - defer f.Close() +func readMask(publicInputs string) (*big.Int, error) { var output []string - var decoder = json.NewDecoder(f) - err = decoder.Decode(&output) - if err != nil { + if err := json.Unmarshal([]byte(publicInputs), &output); err != nil { return nil, err } if len(output) != 3 { @@ -204,3 +251,126 @@ type InputPair struct { EncodingKeyIn string `json:"encodingKeyIn"` XIn string `json:"xIn"` } + +func toG1Point(s []string) (G1Point, error) { + var x, y big.Int + _, ok := x.SetString(s[0], 10) + if !ok { + return G1Point{}, fmt.Errorf("invalid number %s", s[0]) + } + _, ok = y.SetString(s[1], 10) + if !ok { + return G1Point{}, fmt.Errorf("invalid number %s", s[1]) + } + return G1Point{&x, &y}, nil +} + +func toG2Point(s [][]string) (G2Point, error) { + var x, y [2]*big.Int + for i, vi := range s { + for j, vj := range vi { + z := new(big.Int) + _, ok := z.SetString(vj, 10) + if !ok { + return G2Point{}, fmt.Errorf("invalid number %s", vj) + } + // swap so that it can be accepted by the verifier contract + if i == 0 { + x[1-j] = z + } else { + y[1-j] = z + } + } + } + return G2Point{x, y}, nil +} + +type ZKProof struct { + A G1Point `json:"A"` + B G2Point `json:"B"` + C G1Point `json:"C"` +} + +type G1Point struct { + X *big.Int + Y *big.Int +} + +func (p G1Point) MarshalJSON() ([]byte, error) { + return json.Marshal(&struct { + X string `json:"X"` + Y string `json:"Y"` + }{ + X: p.X.String(), + Y: p.Y.String(), + }) +} + +func (p *G1Point) UnmarshalJSON(b []byte) error { + var values struct { + X string `json:"X"` + Y string `json:"Y"` + } + err := json.Unmarshal(b, &values) + if err != nil { + fmt.Printf("Unmarshal %v\n", err) + return err + } + p.X = new(big.Int) + _, ok := p.X.SetString(values.X, 10) + if !ok { + return err + } + p.Y = new(big.Int) + _, ok = p.Y.SetString(values.Y, 10) + if !ok { + return err + } + return nil +} + +type G2Point struct { + X [2]*big.Int `json:"X"` + Y [2]*big.Int `json:"Y"` +} + +func (p *G2Point) UnmarshalJSON(b []byte) error { + var values struct { + X [2]string `json:"X"` + Y [2]string `json:"Y"` + } + err := json.Unmarshal(b, &values) + if err != nil { + fmt.Printf("Unmarshal %v\n", err) + return err + } + for j, vj := range values.X { + z := new(big.Int) + _, ok := z.SetString(vj, 10) + if !ok { + return err + } + // swap so that it can be accepted by the verifier contract + p.X[1-j] = z + } + for j, vj := range values.Y { + z := new(big.Int) + _, ok := z.SetString(vj, 10) + if !ok { + return err + } + // swap so that it can be accepted by the verifier contract + p.Y[1-j] = z + } + return nil +} + +func (p G2Point) MarshalJSON() ([]byte, error) { + return json.Marshal(&struct { + X [2]string `json:"X"` + Y [2]string `json:"Y"` + }{ + X: [2]string{p.X[0].String(), p.X[1].String()}, + Y: [2]string{p.Y[0].String(), p.Y[1].String()}, + }) +} diff --git a/go.mod b/go.mod index 40b539f9..12ec56cd 100644 --- a/go.mod +++ b/go.mod @@ -56,7 +56,7 @@ require ( github.com/hashicorp/golang-lru/arc/v2 v2.0.5 // indirect github.com/herumi/bls-eth-go-binary v1.28.1 // indirect github.com/huin/goupnp v1.3.0 // indirect - github.com/iden3/go-rapidsnark/types v0.0.2 // indirect + github.com/iden3/go-rapidsnark/types v0.0.3 // indirect github.com/iden3/go-rapidsnark/witness/v2 v2.0.0 // indirect github.com/iden3/wasmer-go v0.0.1 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect diff --git a/go.sum b/go.sum index 72cac55a..79a7ebff 100644 --- a/go.sum +++ b/go.sum @@ -313,6 +313,8 @@ github.com/iden3/go-rapidsnark/prover v0.0.10 h1:NvOfRPpex/k646UsqOcUy7a7uVl17t4 github.com/iden3/go-rapidsnark/prover v0.0.10/go.mod h1:wgDsmKOGCuWGtgVtuW9ARWNguNr4NJAIyg2G7+uTax0= github.com/iden3/go-rapidsnark/types v0.0.2 h1:CjJSrlbWchHzuMRdxSYrEh7n/akP+Z2PLNbwT5yBmQY= github.com/iden3/go-rapidsnark/types v0.0.2/go.mod h1:ApgcaUxKIgSRA6fAeFxK7p+lgXXfG4oA2HN5DhFlfF4= +github.com/iden3/go-rapidsnark/types v0.0.3 h1:f0s1Qdut1qHe1O67+m+xUVRBPwSXnq5j0xSrBi0jqM4= +github.com/iden3/go-rapidsnark/types v0.0.3/go.mod h1:ApgcaUxKIgSRA6fAeFxK7p+lgXXfG4oA2HN5DhFlfF4= github.com/iden3/go-rapidsnark/witness/v2 v2.0.0 h1:mkY6VDfwKVJc83QGKmwVXY2LYepidPrFAxskrjr8UCs= github.com/iden3/go-rapidsnark/witness/v2 v2.0.0/go.mod h1:3JRjqUfW1hgI9hzLDO0v8z/DUkR0ZUehhYLlnIfRxnA= github.com/iden3/go-rapidsnark/witness/wasmer v0.0.0-20230524142950-0986cf057d4e h1:lqrevdLsG1k8ieaxgUQccf3unf73m3zmkHJ3oIdld90= diff --git a/integration_tests/node_mine_test.go b/integration_tests/node_mine_test.go index 7c17edf9..815b9016 100644 --- a/integration_tests/node_mine_test.go +++ b/integration_tests/node_mine_test.go @@ -404,9 +404,9 @@ func initMiningConfig(t *testing.T, l1Contract common.Address, client *eth.Polli } miningConfig.PrepaidAmount = new(big.Int).SetBytes(result) - miningConfig.ZKeyFileName = zkeyFile2 + miningConfig.ZKeyFileName = zkey2Name proverPath, _ := filepath.Abs(prPath) - zkeyFull := filepath.Join(proverPath, snarkLibDir, miningConfig.ZKeyFileName) + zkeyFull := filepath.Join(proverPath, prover.SnarkLib, miningConfig.ZKeyFileName) if _, err := os.Stat(zkeyFull); os.IsNotExist(err) { t.Fatalf("%s not found", zkeyFull) } diff --git a/integration_tests/zk_prover2_test.go b/integration_tests/zk_prover2_test.go index 4f150d74..27de7eaf 100644 --- a/integration_tests/zk_prover2_test.go +++ b/integration_tests/zk_prover2_test.go @@ -7,11 +7,11 @@ package integration import ( "context" - "encoding/json" "fmt" "math/big" "os" "path/filepath" + "reflect" "testing" "github.com/ethstorage/go-ethstorage/ethstorage/prover" @@ -23,13 +23,12 @@ import ( ) const ( - vKeyName2 = "blob_poseidon2_verification_key.json" - zkeyFile2 = "blob_poseidon2.zkey" + zkey2Name = "blob_poseidon2.zkey" ) func TestZKProver_GenerateZKProof(t *testing.T) { proverPath, _ := filepath.Abs(prPath) - zkeyFull := filepath.Join(proverPath, snarkLibDir, zkeyFile2) + zkeyFull := filepath.Join(proverPath, prover.SnarkLib, zkey2Name) if _, err := os.Stat(zkeyFull); os.IsNotExist(err) { t.Fatalf("%s not found", zkeyFull) } @@ -46,28 +45,34 @@ func TestZKProver_GenerateZKProof(t *testing.T) { "1", "12199007973319674300030596965685270475268514105269206407619072166392043015767", } - libDir := filepath.Join(proverPath, snarkLibDir) - p := prover.NewZKProverInternal(proverPath, zkeyFile2, lg) + libDir := filepath.Join(proverPath, prover.SnarkLib) + p, err := prover.NewZKProver(libDir, zkey2Name, prover.Wasm2Name, lg) + if err != nil { + t.Errorf("NewZKProver() error = %v", err) + return + } t.Run("zk test", func(t *testing.T) { - proof, masks, err := p.GenerateZKProof(encodingKeys, sampleIdxs) + inputs, err := p.GenerateInputs(encodingKeys, sampleIdxs) if err != nil { - t.Errorf("ZKProver.GenerateZKProof() error = %v ", err) + t.Errorf("ZKProver.GenerateInputs() error = %v", err) return } - tempDir := crypto.Keccak256Hash([]byte(fmt.Sprint(encodingKeys, sampleIdxs))) - buildDir := filepath.Join(proverPath, snarkBuildDir, common.Bytes2Hex(tempDir[:])) - defer os.RemoveAll(buildDir) - - xIn, err := readXIn2(buildDir) - if err != nil { - t.Fatalf("get xIn failed %v", err) + vxIn, ok := inputs["xIn"].([]interface{}) + if !ok { + t.Errorf("ZKProver.GenerateInputs(): invalid inputs") } - for i, x := range xIn { - if x != xIns[i] { - t.Errorf("ZKProver.GenerateZKProof() xIn[%d] = %v, expected %v", i, x, xIns[i]) + for i, xIn := range xIns { + if reflect.DeepEqual(vxIn[i], xIn) { + t.Errorf("ZKProver.GenerateInputs() xIn = %v, want %v", inputs["xIn"], xIns) return } } + proof, masks, err := p.GenerateZKProof(encodingKeys, sampleIdxs) + if err != nil { + t.Errorf("ZKProver.GenerateZKProof() error = %v ", err) + return + } + t.Logf("proof: %+v", proof) for i, encodingKey := range encodingKeys { maskGo, err := GenerateMask(encodingKey, sampleIdxs[i]) if err != nil { @@ -79,11 +84,6 @@ func TestZKProver_GenerateZKProof(t *testing.T) { return } } - err = localVerify(t, libDir, buildDir, vKeyName2) - if err != nil { - t.Errorf("ZKProver.GenerateZKProof() localVerify failed: %v", err) - return - } err = verifyProof(t, masks, proof) if err != nil { t.Errorf("ZKProver.GenerateZKProof() verifyProof err: %v", err) @@ -99,21 +99,6 @@ func TestZKProver_GenerateZKProof(t *testing.T) { }) } -func readXIn2(buildDir string) ([]string, error) { - f, err := os.Open(filepath.Join(buildDir, inputName)) - if err != nil { - return nil, err - } - defer f.Close() - var input prover.InputPairV2 - var decoder = json.NewDecoder(f) - err = decoder.Decode(&input) - if err != nil { - return nil, err - } - return input.XIn, nil -} - func verifyDecodeSample2(t *testing.T, masks []*big.Int, proof []byte) error { ctx := context.Background() client, err := ethclient.DialContext(ctx, l1Endpoint) diff --git a/integration_tests/zk_prover_test.go b/integration_tests/zk_prover_test.go index e1056df7..97a9a476 100644 --- a/integration_tests/zk_prover_test.go +++ b/integration_tests/zk_prover_test.go @@ -7,15 +7,11 @@ package integration import ( "context" - "encoding/json" "fmt" "log" "math/big" "os" - "os/exec" "path/filepath" - "reflect" - "strings" "testing" "github.com/consensys/gnark-crypto/ecc/bn254/fr" @@ -29,14 +25,9 @@ import ( ) const ( - l1ContractV1 = "0xc3208C27285ed9516F21a89053326Bb895DD78F7" - snarkBuildDir = "snarkbuild" - inputName = "input_blob_poseidon.json" - proofName = "proof_blob_poseidon.json" - publicName = "public_blob_poseidon.json" - vKeyName = "blob_poseidon_verification_key.json" - prPath = "../ethstorage/prover" - zkeyFile = "blob_poseidon.zkey" + l1ContractV1 = "0xc3208C27285ed9516F21a89053326Bb895DD78F7" + prPath = "../ethstorage/prover" + zkeyFile = "blob_poseidon.zkey" ) func TestZKProver_GenerateZKProofPerSample(t *testing.T) { @@ -75,7 +66,10 @@ func TestZKProver_GenerateZKProofPerSample(t *testing.T) { }, } libDir := filepath.Join(proverPath, prover.SnarkLib) - p := prover.NewZKProverInternal(proverPath, zkeyFile, lg) + p, err := prover.NewZKProver(libDir, zkeyFile, prover.WasmName, lg) + if err != nil { + t.Fatal(err) + } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { maskGo, err := GenerateMask(tt.args.encodingKey, tt.args.chunkIdx) @@ -83,38 +77,21 @@ func TestZKProver_GenerateZKProofPerSample(t *testing.T) { t.Errorf("GenerateMask() error = %v, wantErr %v", err, tt.wantErr) return } - proof, mask, err := p.GenerateZKProofPerSample(tt.args.encodingKey, tt.args.chunkIdx) + proofRaw, mask, err := p.GenerateZKProofPerSample(tt.args.encodingKey, tt.args.chunkIdx) if (err != nil) != tt.wantErr { t.Errorf("ZKProver.GenerateZKProofPerSample() error = %v, wantErr %v", err, tt.wantErr) return } - buildDir := filepath.Join(proverPath, snarkBuildDir, strings.Join([]string{ - tt.args.encodingKey.Hex(), - fmt.Sprint(tt.args.chunkIdx), - }, "-")) - xIn, err := readXIn(buildDir) - if err != nil { - t.Fatalf("get xIn failed %v", err) - } - if !reflect.DeepEqual(xIn, tt.xIn) { - t.Errorf("ZKProver.GenerateZKProofPerSample() xIn = %v, want %v", xIn, tt.xIn) - } if maskGo.Cmp(mask) != 0 { t.Errorf("ZKProver.GenerateZKProofPerSample() mask = %v, GenerateMask %v", mask, maskGo) return } - err = localVerify(t, libDir, buildDir, vKeyName) - if (err != nil) != tt.wantErr { - t.Errorf("ZKProver.GenerateZKProofPerSample() localVerify failed: %v", err) - return - } - err = verifyDecodeSample(proof, tt.args.chunkIdx, tt.args.encodingKey, mask) + err = verifyDecodeSample(proofRaw, tt.args.chunkIdx, tt.args.encodingKey, mask) if (err != nil) != tt.wantErr { t.Errorf("ZKProver.GenerateZKProofPerSample() verifyDecodeSample err: %v", err) return } t.Log("verifyDecodeSample success!") - os.RemoveAll(buildDir) }) } } @@ -133,36 +110,6 @@ func GenerateMask(encodingKey common.Hash, chunkIdx uint64) (*big.Int, error) { return new(big.Int).SetBytes(mask), nil } -func readXIn(buildDir string) (string, error) { - f, err := os.Open(filepath.Join(buildDir, inputName)) - if err != nil { - return "", err - } - defer f.Close() - var input prover.InputPair - var decoder = json.NewDecoder(f) - err = decoder.Decode(&input) - if err != nil { - return "", err - } - return input.XIn, nil -} - -func localVerify(t *testing.T, libDir, buildDir, vKeyName string) error { - cmd := exec.Command("snarkjs", "groth16", "verify", - filepath.Join(libDir, vKeyName), - filepath.Join(buildDir, publicName), - filepath.Join(buildDir, proofName), - ) - out, err := cmd.Output() - if err != nil { - t.Logf("Local verify failed: %v, cmd: %s, output: %v", err, cmd.String(), string(out)) - return err - } - t.Logf("Local verify done. result: %s", out) - return nil -} - func verifyDecodeSample(proofBytes []byte, trunkIdx uint64, encodingKey common.Hash, mask *big.Int) error { ctx := context.Background() client, err := ethclient.DialContext(ctx, l1Endpoint) @@ -211,111 +158,21 @@ func verifyDecodeSample(proofBytes []byte, trunkIdx uint64, encodingKey common.H return callVerify(calldata, common.HexToAddress(l1ContractV1)) } -func parseProof(data []byte) ZKProof { - zkProof := ZKProof{} +func parseProof(data []byte) prover.ZKProof { + zkProof := prover.ZKProof{} x1 := new(big.Int).SetBytes(data[:32]) y1 := new(big.Int).SetBytes(data[32:64]) - zkProof.A = G1Point{X: x1, Y: y1} + zkProof.A = prover.G1Point{X: x1, Y: y1} var x2 [2]*big.Int var y2 [2]*big.Int x2[0] = new(big.Int).SetBytes(data[64:96]) x2[1] = new(big.Int).SetBytes(data[96:128]) y2[0] = new(big.Int).SetBytes(data[128:160]) y2[1] = new(big.Int).SetBytes(data[160:192]) - zkProof.B = G2Point{X: x2, Y: y2} + zkProof.B = prover.G2Point{X: x2, Y: y2} x3 := new(big.Int).SetBytes(data[192:224]) y3 := new(big.Int).SetBytes(data[224:256]) - zkProof.C = G1Point{X: x3, Y: y3} + zkProof.C = prover.G1Point{X: x3, Y: y3} return zkProof } - -type ZKProof struct { - A G1Point `json:"A"` - B G2Point `json:"B"` - C G1Point `json:"C"` -} - -type G1Point struct { - X *big.Int - Y *big.Int -} - -func (p G1Point) MarshalJSON() ([]byte, error) { - return json.Marshal(&struct { - X string `json:"X"` - Y string `json:"Y"` - }{ - X: p.X.String(), - Y: p.Y.String(), - }) -} - -func (p *G1Point) UnmarshalJSON(b []byte) error { - var values struct { - X string `json:"X"` - Y string `json:"Y"` - } - err := json.Unmarshal(b, &values) - if err != nil { - fmt.Printf("Unmarshal %v\n", err) - return err - } - p.X = new(big.Int) - _, ok := p.X.SetString(values.X, 10) - if !ok { - return err - } - p.Y = new(big.Int) - _, ok = p.Y.SetString(values.Y, 10) - if !ok { - return err - } - return nil -} - -type G2Point struct { - X [2]*big.Int `json:"X"` - Y [2]*big.Int `json:"Y"` -} - -func (p *G2Point) UnmarshalJSON(b []byte) error { - var values struct { - X [2]string `json:"X"` - Y [2]string `json:"Y"` - } - err := json.Unmarshal(b, &values) - if err != nil { - fmt.Printf("Unmarshal %v\n", err) - return err - } - for j, vj := range values.X { - z := new(big.Int) - _, ok := z.SetString(vj, 10) - if !ok { - return err - } - // swap so that it can be accepted by the verifier contract - p.X[1-j] = z - } - for j, vj := range values.Y { - z := new(big.Int) - _, ok := z.SetString(vj, 10) - if !ok { - return err - } - // swap so that it can be accepted by the verifier contract - p.Y[1-j] = z - } - return nil -} - -func (p G2Point) MarshalJSON() ([]byte, error) { - return json.Marshal(&struct { - X [2]string `json:"X"` - Y [2]string `json:"Y"` - }{ - X: [2]string{p.X[0].String(), p.X[1].String()}, - Y: [2]string{p.Y[0].String(), p.Y[1].String()}, - }) -} From e0b113e8d910e9f1c71446b156c24baea73f4f94 Mon Sep 17 00:00:00 2001 From: syntrust Date: Tue, 9 Jan 2024 17:43:57 +0800 Subject: [PATCH 06/45] refactor --- ethstorage/prover/kzg_poseidon_prover.go | 30 ++--- ethstorage/prover/zk_prover.go | 134 +++++------------------ ethstorage/prover/zk_prover2.go | 90 +++++++++++++++ go.mod | 2 + go.sum | 4 + integration_tests/node_mine_test.go | 2 +- integration_tests/run_tests.sh | 4 +- integration_tests/zk_prover2_test.go | 15 ++- integration_tests/zk_prover_test.go | 52 +++++++-- 9 files changed, 190 insertions(+), 143 deletions(-) create mode 100644 ethstorage/prover/zk_prover2.go diff --git a/ethstorage/prover/kzg_poseidon_prover.go b/ethstorage/prover/kzg_poseidon_prover.go index 7d63db23..14c3de87 100644 --- a/ethstorage/prover/kzg_poseidon_prover.go +++ b/ethstorage/prover/kzg_poseidon_prover.go @@ -21,17 +21,17 @@ const ( ) type KZGPoseidonProver struct { - version uint64 - libDir string - zkey string - lg log.Logger + zkMode uint64 + libDir string + zkey string + lg log.Logger } // Prover that can be used directly by miner to prove both KZG and Poseidon hash // workingDir specifies the working directory of the command relative to the caller. // zkeyFileName specifies the zkey file name to generate snark proof // returns a prover that can generate a combined KZG + zk proof -func NewKZGPoseidonProver(workingDir, zkeyFileName string, version uint64, lg log.Logger) KZGPoseidonProver { +func NewKZGPoseidonProver(workingDir, zkeyFileName string, zkMode uint64, lg log.Logger) KZGPoseidonProver { // check dependencies when es-node starts libDir := filepath.Join(workingDir, SnarkLib) if _, err := os.Stat(libDir); errors.Is(err, os.ErrNotExist) { @@ -42,21 +42,21 @@ func NewKZGPoseidonProver(workingDir, zkeyFileName string, version uint64, lg lo lg.Crit("Init ZK prover failed", "error", "zkey does not exist", "dir", zkeyFile) } var wasmFile string - if version == 2 { + if zkMode == 2 { wasmFile = filepath.Join(libDir, Wasm2Name) - } else if version == 1 { + } else if zkMode == 1 { wasmFile = filepath.Join(libDir, WasmName) } else { - lg.Crit("Init ZK prover failed", "error", "invalid version", "version", version) + lg.Crit("Init ZK prover failed", "error", "invalid zkMode", "mode", zkMode) } if _, err := os.Stat(zkeyFile); errors.Is(err, os.ErrNotExist) { lg.Crit("Init ZK prover failed", "error", "wasm does not exist", "dir", wasmFile) } return KZGPoseidonProver{ - version: version, - libDir: libDir, - zkey: zkeyFileName, - lg: lg, + zkMode: zkMode, + libDir: libDir, + zkey: zkeyFileName, + lg: lg, } } @@ -78,7 +78,7 @@ func (p *KZGPoseidonProver) GetStorageProof(data [][]byte, encodingKeys []common } var zkProofs [][]byte var masks []*big.Int - if p.version == 1 { + if p.zkMode == 1 { prvr, err := NewZKProver(p.libDir, p.zkey, WasmName, p.lg) if err != nil { return nil, nil, nil, err @@ -91,7 +91,7 @@ func (p *KZGPoseidonProver) GetStorageProof(data [][]byte, encodingKeys []common zkProofs = append(zkProofs, zkProof) masks = append(masks, mask) } - } else if p.version == 2 { + } else if p.zkMode == 2 { prvr, err := NewZKProver(p.libDir, p.zkey, Wasm2Name, p.lg) if err != nil { return nil, nil, nil, err @@ -103,7 +103,7 @@ func (p *KZGPoseidonProver) GetStorageProof(data [][]byte, encodingKeys []common zkProofs = append(zkProofs, zkProof) masks = msks } else { - return nil, nil, nil, fmt.Errorf("invalid zk proof version") + return nil, nil, nil, fmt.Errorf("invalid zk proof mode") } return masks, zkProofs, peInputs, nil } diff --git a/ethstorage/prover/zk_prover.go b/ethstorage/prover/zk_prover.go index 14ce199f..7510a5f3 100644 --- a/ethstorage/prover/zk_prover.go +++ b/ethstorage/prover/zk_prover.go @@ -20,7 +20,7 @@ import ( "github.com/iden3/go-rapidsnark/prover" "github.com/iden3/go-rapidsnark/types" "github.com/iden3/go-rapidsnark/witness/v2" - "github.com/iden3/go-rapidsnark/witness/wasmer" + "github.com/iden3/go-rapidsnark/witness/wazero" ) type ZKProver struct { @@ -35,8 +35,9 @@ func NewZKProver(libDir, zkeyName, wasmName string, lg log.Logger) (*ZKProver, e lg.Error("Read wasm file failed", "error", err) return nil, err } - calc, err := witness.NewCalculator(wasmBytes, witness.WithWasmEngine(wasmer.NewCircom2WitnessCalculator)) + calc, err := witness.NewCalculator(wasmBytes, witness.WithWasmEngine(wazero.NewCircom2WZWitnessCalculator)) if err != nil { + lg.Error("Create witness calculator failed", "error", err) return nil, err } zkey, err := os.ReadFile(filepath.Join(libDir, zkeyName)) @@ -51,90 +52,37 @@ func NewZKProver(libDir, zkeyName, wasmName string, lg log.Logger) (*ZKProver, e }, nil } -// Generate ZK Proof for the given encoding keys and sample indexes -func (p *ZKProver) GenerateZKProof(encodingKeys []common.Hash, sampleIdxs []uint64) ([]byte, []*big.Int, error) { - for i, idx := range sampleIdxs { - p.lg.Debug("Generate zk proof", "encodingKey", encodingKeys[i], "sampleIdx", sampleIdxs[i]) - if int(idx) >= eth.FieldElementsPerBlob { - return nil, nil, fmt.Errorf("chunk index out of scope: %d", idx) - } +// Generate ZK Proof for the given encoding key and sample index +func (p *ZKProver) GenerateZKProofPerSample(encodingKey common.Hash, sampleIdx uint64) ([]byte, *big.Int, error) { + p.lg.Debug("Generate zk proof", "encodingKey", encodingKey.Hex(), "sampleIdx", sampleIdx) + if int(sampleIdx) >= eth.FieldElementsPerBlob { + return nil, nil, fmt.Errorf("chunk index out of scope: %d", sampleIdx) } start := time.Now() defer func(start time.Time) { dur := time.Since(start) - p.lg.Info("Generate zk proof done", "sampleIdx", sampleIdxs, "took(sec)", dur.Seconds()) + p.lg.Info("Generate zk proof", "sampleIdx", sampleIdx, "timeUsed(s)", dur.Seconds()) }(start) - parsedInputs, err := p.GenerateInputs(encodingKeys, sampleIdxs) + inputBytes, err := p.GenerateInput(encodingKey, sampleIdx) if err != nil { p.lg.Error("Generate inputs failed", "error", err) return nil, nil, err } - wtnsBytes, err := p.calc.CalculateWTNSBin(parsedInputs, true) - if err != nil { - p.lg.Error("Calculate witness failed", "error", err) - return nil, nil, err - } - proofRaw, publicInputs, err := prover.Groth16ProverRaw(p.zkey, wtnsBytes) + proof, publicInputs, err := p.prove(inputBytes) if err != nil { p.lg.Error("Prove failed", "error", err) return nil, nil, err } - proof, err := readProof(proofRaw) - if err != nil { - p.lg.Error("Read proof failed", "error", err) - return nil, nil, err - } - p.lg.Debug("Proof generated", "proof", proof) - masks, err := readMasks(publicInputs) + mask, err := readMask(publicInputs) if err != nil { - p.lg.Error("Read masks failed", "error", err) return nil, nil, err } - return proof, masks, nil -} -func (p *ZKProver) GenerateInputs(encodingKeys []common.Hash, sampleIdxs []uint64) (map[string]interface{}, error) { - var encodingKeyModStr, xInStr []string - for i, sampleIdx := range sampleIdxs { - var b fr.Element - var exp big.Int - exp.Div(exp.Sub(fr.Modulus(), common.Big1), big.NewInt(int64(eth.FieldElementsPerBlob))) - ru := b.Exp(*b.SetInt64(5), &exp) - xIn := ru.Exp(*ru, new(big.Int).SetUint64(sampleIdx)) - xInStr = append(xInStr, xIn.String()) - encodingKeyMod := fr.Modulus().Mod(encodingKeys[i].Big(), fr.Modulus()) - encodingKeyModStr = append(encodingKeyModStr, hexutil.Encode(encodingKeyMod.Bytes())) - } - inputObj := InputPairV2{ - EncodingKeyIn: encodingKeyModStr, - XIn: xInStr, - } - p.lg.Debug("Generate zk proof", "input", inputObj) - inputBytes, err := json.Marshal(inputObj) - if err != nil { - p.lg.Error("Marshal input failed", "error", err) - return nil, err - } - parsedInputs, err := witness.ParseInputs(inputBytes) - if err != nil { - p.lg.Error("Parse input failed", "error", err) - return nil, err - } - return parsedInputs, nil + p.lg.Debug("Generate zk proof", "mask", mask) + return proof, mask, nil } -// Generate ZK Proof for the given encoding key and sample index -func (p *ZKProver) GenerateZKProofPerSample(encodingKey common.Hash, sampleIdx uint64) ([]byte, *big.Int, error) { - p.lg.Debug("Generate zk proof", "encodingKey", encodingKey.Hex(), "sampleIdx", sampleIdx) - if int(sampleIdx) >= eth.FieldElementsPerBlob { - return nil, nil, fmt.Errorf("chunk index out of scope: %d", sampleIdx) - } - start := time.Now() - defer func(start time.Time) { - dur := time.Since(start) - p.lg.Info("Generate zk proof", "sampleIdx", sampleIdx, "took(sec)", dur.Seconds()) - }(start) - +func (p *ZKProver) GenerateInput(encodingKey common.Hash, sampleIdx uint64) ([]byte, error) { var b fr.Element var exp big.Int exp.Div(exp.Sub(fr.Modulus(), common.Big1), big.NewInt(int64(eth.FieldElementsPerBlob))) @@ -146,37 +94,32 @@ func (p *ZKProver) GenerateZKProofPerSample(encodingKey common.Hash, sampleIdx u XIn: xIn.String(), } p.lg.Debug("Generate zk proof", "input", inputObj) - inputBytes, err := json.Marshal(inputObj) - if err != nil { - p.lg.Error("Marshal input failed", "error", err) - return nil, nil, err - } + return json.Marshal(inputObj) +} + +func (p *ZKProver) prove(inputBytes []byte) ([]byte, string, error) { parsedInputs, err := witness.ParseInputs(inputBytes) if err != nil { p.lg.Error("Parse input failed", "error", err) - return nil, nil, err + return nil, "", err } wtnsBytes, err := p.calc.CalculateWTNSBin(parsedInputs, true) if err != nil { p.lg.Error("Calculate witness failed", "error", err) - return nil, nil, err + return nil, "", err } proofRaw, publicInputs, err := prover.Groth16ProverRaw(p.zkey, wtnsBytes) if err != nil { p.lg.Error("Prove failed", "error", err) - return nil, nil, err + return nil, "", err } + p.lg.Debug("Generate zk proof", "publicInputs", publicInputs) proof, err := readProof(proofRaw) if err != nil { p.lg.Error("Read proof failed", "error", err) - return nil, nil, err + return nil, "", err } - mask, err := readMask(publicInputs) - if err != nil { - return nil, nil, err - } - p.lg.Debug("Generate zk proof", "mask", mask) - return proof, mask, nil + return proof, publicInputs, nil } func readProof(proofRaw string) ([]byte, error) { @@ -211,22 +154,6 @@ func readProof(proofRaw string) ([]byte, error) { return packed, nil } -func readMasks(publicInputs string) ([]*big.Int, error) { - var output []string - if err := json.Unmarshal([]byte(publicInputs), &output); err != nil { - return nil, err - } - var masks []*big.Int - for _, v := range output { - mask, ok := new(big.Int).SetString(v, 0) - if !ok { - return masks, fmt.Errorf("invalid mask %v", v) - } - masks = append(masks, mask) - } - return masks, nil -} - func readMask(publicInputs string) (*big.Int, error) { var output []string if err := json.Unmarshal([]byte(publicInputs), &output); err != nil { @@ -242,11 +169,6 @@ func readMask(publicInputs string) (*big.Int, error) { return mask, nil } -type InputPairV2 struct { - EncodingKeyIn []string `json:"encodingKeyIn"` - XIn []string `json:"xIn"` -} - type InputPair struct { EncodingKeyIn string `json:"encodingKeyIn"` XIn string `json:"xIn"` @@ -285,12 +207,6 @@ func toG2Point(s [][]string) (G2Point, error) { return G2Point{x, y}, nil } -type ZKProof struct { - A G1Point `json:"A"` - B G2Point `json:"B"` - C G1Point `json:"C"` -} - type G1Point struct { X *big.Int Y *big.Int diff --git a/ethstorage/prover/zk_prover2.go b/ethstorage/prover/zk_prover2.go new file mode 100644 index 00000000..aef29600 --- /dev/null +++ b/ethstorage/prover/zk_prover2.go @@ -0,0 +1,90 @@ +// Copyright 2022-2023, EthStorage. +// For license information, see https://github.com/ethstorage/es-node/blob/main/LICENSE + +package prover + +import ( + "encoding/json" + "fmt" + "math/big" + "time" + + "github.com/consensys/gnark-crypto/ecc/bn254/fr" + "github.com/crate-crypto/go-proto-danksharding-crypto/eth" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" +) + +// Generate ZK Proof for the given encoding keys and sample indexes +func (p *ZKProver) GenerateZKProof(encodingKeys []common.Hash, sampleIdxs []uint64) ([]byte, []*big.Int, error) { + for i, idx := range sampleIdxs { + p.lg.Debug("Generate zk proof", "encodingKey", encodingKeys[i], "sampleIdx", sampleIdxs[i]) + if int(idx) >= eth.FieldElementsPerBlob { + return nil, nil, fmt.Errorf("chunk index out of scope: %d", idx) + } + } + start := time.Now() + defer func(start time.Time) { + dur := time.Since(start) + p.lg.Info("Generate zk proof done", "sampleIdx", sampleIdxs, "timeUsed(s)", dur.Seconds()) + }(start) + + inputBytes, err := p.GenerateInputs(encodingKeys, sampleIdxs) + if err != nil { + p.lg.Error("Generate inputs failed", "error", err) + return nil, nil, err + } + proof, publicInputs, err := p.prove(inputBytes) + if err != nil { + p.lg.Error("Prove failed", "error", err) + return nil, nil, err + } + masks, err := readMasks(publicInputs) + if err != nil { + p.lg.Error("Read masks failed", "error", err) + return nil, nil, err + } + p.lg.Debug("Generate zk proof", "masks", masks) + return proof, masks, nil +} + +func (p *ZKProver) GenerateInputs(encodingKeys []common.Hash, sampleIdxs []uint64) ([]byte, error) { + var encodingKeyModStr, xInStr []string + for i, sampleIdx := range sampleIdxs { + var b fr.Element + var exp big.Int + exp.Div(exp.Sub(fr.Modulus(), common.Big1), big.NewInt(int64(eth.FieldElementsPerBlob))) + ru := b.Exp(*b.SetInt64(5), &exp) + xIn := ru.Exp(*ru, new(big.Int).SetUint64(sampleIdx)) + xInStr = append(xInStr, xIn.String()) + encodingKeyMod := fr.Modulus().Mod(encodingKeys[i].Big(), fr.Modulus()) + encodingKeyModStr = append(encodingKeyModStr, hexutil.Encode(encodingKeyMod.Bytes())) + } + inputObj := InputPairV2{ + EncodingKeyIn: encodingKeyModStr, + XIn: xInStr, + } + p.lg.Debug("Generate zk proof", "input", inputObj) + return json.Marshal(inputObj) +} + +func readMasks(publicInputs string) ([]*big.Int, error) { + var output []string + if err := json.Unmarshal([]byte(publicInputs), &output); err != nil { + return nil, err + } + var masks []*big.Int + for _, v := range output { + mask, ok := new(big.Int).SetString(v, 0) + if !ok { + return masks, fmt.Errorf("invalid mask %v", v) + } + masks = append(masks, mask) + } + return masks, nil +} + +type InputPairV2 struct { + EncodingKeyIn []string `json:"encodingKeyIn"` + XIn []string `json:"xIn"` +} diff --git a/go.mod b/go.mod index 12ec56cd..bf34f95d 100644 --- a/go.mod +++ b/go.mod @@ -68,6 +68,7 @@ require ( github.com/stretchr/testify v1.8.4 // indirect github.com/supranational/blst v0.3.11 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a // indirect + github.com/tetratelabs/wazero v1.1.0 // indirect github.com/tyler-smith/go-bip39 v1.1.0 // indirect github.com/urfave/cli/v2 v2.25.7 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect @@ -108,6 +109,7 @@ require ( github.com/hashicorp/golang-lru/v2 v2.0.5 github.com/iden3/go-rapidsnark/prover v0.0.10 github.com/iden3/go-rapidsnark/witness/wasmer v0.0.0-20230524142950-0986cf057d4e + github.com/iden3/go-rapidsnark/witness/wazero v0.0.1 github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/ipfs/go-cid v0.4.1 // indirect github.com/ipfs/go-ds-leveldb v0.5.0 diff --git a/go.sum b/go.sum index 79a7ebff..91cb05d3 100644 --- a/go.sum +++ b/go.sum @@ -319,6 +319,8 @@ github.com/iden3/go-rapidsnark/witness/v2 v2.0.0 h1:mkY6VDfwKVJc83QGKmwVXY2LYepi github.com/iden3/go-rapidsnark/witness/v2 v2.0.0/go.mod h1:3JRjqUfW1hgI9hzLDO0v8z/DUkR0ZUehhYLlnIfRxnA= github.com/iden3/go-rapidsnark/witness/wasmer v0.0.0-20230524142950-0986cf057d4e h1:lqrevdLsG1k8ieaxgUQccf3unf73m3zmkHJ3oIdld90= github.com/iden3/go-rapidsnark/witness/wasmer v0.0.0-20230524142950-0986cf057d4e/go.mod h1:WUtPVKXrhfZHJXavwId2+8J/fKMHQ92N0MZDxt8sfEA= +github.com/iden3/go-rapidsnark/witness/wazero v0.0.1 h1:NSLCXVNWMSn+ilTCNUtIqbu9BViiICasq4FrMNCAds4= +github.com/iden3/go-rapidsnark/witness/wazero v0.0.1/go.mod h1:UEBifEzw62T6VzIHJeHuUgeLg2U/J9ttf7hOwQEqnYk= github.com/iden3/wasmer-go v0.0.1 h1:TZKh8Se8B/73PvWrcu+FTU9L1k5XYAmtFbioj7l0Uog= github.com/iden3/wasmer-go v0.0.1/go.mod h1:ZnZBAO012M7o+Q1INXLRIxKQgEcH2FuwL0Iga8A4ufg= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= @@ -657,6 +659,8 @@ github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpP github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a h1:1ur3QoCqvE5fl+nylMaIr9PVV1w343YRDtsy+Rwu7XI= github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= +github.com/tetratelabs/wazero v1.1.0 h1:EByoAhC+QcYpwSZJSs/aV0uokxPwBgKxfiokSUwAknQ= +github.com/tetratelabs/wazero v1.1.0/go.mod h1:wYx2gNRg8/WihJfSDxA1TIL8H+GkfLYm+bIfbblu9VQ= github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= diff --git a/integration_tests/node_mine_test.go b/integration_tests/node_mine_test.go index 38239414..55315bc4 100644 --- a/integration_tests/node_mine_test.go +++ b/integration_tests/node_mine_test.go @@ -74,7 +74,7 @@ func TestMining(t *testing.T) { feed := new(event.Feed) l1api := miner.NewL1MiningAPI(pClient, lg) - pvr := prover.NewKZGPoseidonProver(miningConfig.ZKWorkingDir, zkeyFile, 2, lg) + pvr := prover.NewKZGPoseidonProver(miningConfig.ZKWorkingDir, zkey2Name, 2, lg) mnr := miner.New(miningConfig, storageManager, l1api, &pvr, feed, lg) lg.Info("Initialized miner") diff --git a/integration_tests/run_tests.sh b/integration_tests/run_tests.sh index c3273968..f646a395 100755 --- a/integration_tests/run_tests.sh +++ b/integration_tests/run_tests.sh @@ -42,7 +42,7 @@ echo ES_NODE_STORAGE_L1CONTRACT = $ES_NODE_STORAGE_L1CONTRACT echo ES_NODE_STORAGE_MINER = $ES_NODE_STORAGE_MINER # download zkeys if not yet -zkey_file="./ethstorage/prover/snarkjs/blob_poseidon.zkey" +zkey_file="./ethstorage/prover/snark_lib/blob_poseidon.zkey" if [ ! -e ${zkey_file} ]; then echo "${zkey_file} not found, start downloading..." file_id="1ZLfhYeCXMnbk6wUiBADRAn1mZ8MI_zg-" @@ -50,7 +50,7 @@ if [ ! -e ${zkey_file} ]; then curl -Lb ./cookie "https://drive.google.com/uc?export=download&`echo ${html}|grep -Eo 'confirm=[a-zA-Z0-9\-_]+'`&id=${file_id}" -o ${zkey_file} rm cookie fi -zkey_file="./ethstorage/prover/snarkjs/blob_poseidon2.zkey" +zkey_file="./ethstorage/prover/snark_lib/blob_poseidon2.zkey" if [ ! -e ${zkey_file} ]; then echo "${zkey_file} not found, start downloading..." file_id="1V3QkMpk5UC48Jc62nHXMgzeMb6KE8JRY" diff --git a/integration_tests/zk_prover2_test.go b/integration_tests/zk_prover2_test.go index 27de7eaf..39a7c829 100644 --- a/integration_tests/zk_prover2_test.go +++ b/integration_tests/zk_prover2_test.go @@ -7,6 +7,7 @@ package integration import ( "context" + "encoding/json" "fmt" "math/big" "os" @@ -52,17 +53,24 @@ func TestZKProver_GenerateZKProof(t *testing.T) { return } t.Run("zk test", func(t *testing.T) { - inputs, err := p.GenerateInputs(encodingKeys, sampleIdxs) + inputsBytes, err := p.GenerateInputs(encodingKeys, sampleIdxs) + if err != nil { + t.Errorf("ZKProver.GenerateInputs() error = %v", err) + return + } + var inputs map[string]interface{} + err = json.Unmarshal(inputsBytes, &inputs) if err != nil { t.Errorf("ZKProver.GenerateInputs() error = %v", err) return } vxIn, ok := inputs["xIn"].([]interface{}) if !ok { - t.Errorf("ZKProver.GenerateInputs(): invalid inputs") + t.Errorf("ZKProver.GenerateInputs() type: %v, want []interface{}", reflect.TypeOf(inputs["xIn"])) + return } for i, xIn := range xIns { - if reflect.DeepEqual(vxIn[i], xIn) { + if vxIn[i] != xIn { t.Errorf("ZKProver.GenerateInputs() xIn = %v, want %v", inputs["xIn"], xIns) return } @@ -72,7 +80,6 @@ func TestZKProver_GenerateZKProof(t *testing.T) { t.Errorf("ZKProver.GenerateZKProof() error = %v ", err) return } - t.Logf("proof: %+v", proof) for i, encodingKey := range encodingKeys { maskGo, err := GenerateMask(encodingKey, sampleIdxs[i]) if err != nil { diff --git a/integration_tests/zk_prover_test.go b/integration_tests/zk_prover_test.go index 97a9a476..17af4038 100644 --- a/integration_tests/zk_prover_test.go +++ b/integration_tests/zk_prover_test.go @@ -7,11 +7,13 @@ package integration import ( "context" + "encoding/json" "fmt" "log" "math/big" "os" "path/filepath" + "reflect" "testing" "github.com/consensys/gnark-crypto/ecc/bn254/fr" @@ -27,18 +29,18 @@ import ( const ( l1ContractV1 = "0xc3208C27285ed9516F21a89053326Bb895DD78F7" prPath = "../ethstorage/prover" - zkeyFile = "blob_poseidon.zkey" + zkeyName = "blob_poseidon.zkey" ) func TestZKProver_GenerateZKProofPerSample(t *testing.T) { proverPath, _ := filepath.Abs(prPath) - zkeyFull := filepath.Join(proverPath, prover.SnarkLib, zkeyFile) + zkeyFull := filepath.Join(proverPath, prover.SnarkLib, zkeyName) if _, err := os.Stat(zkeyFull); os.IsNotExist(err) { t.Fatalf("%s not found", zkeyFull) } type args struct { encodingKey common.Hash - chunkIdx uint64 + sampleIdx uint64 } tests := []struct { name string @@ -48,36 +50,56 @@ func TestZKProver_GenerateZKProofPerSample(t *testing.T) { }{ { "test chunk 0", - args{encodingKey: common.HexToHash("0x1"), chunkIdx: 0}, + args{encodingKey: common.HexToHash("0x1"), sampleIdx: 0}, "1", false, }, { "test chunk 2222", - args{encodingKey: common.HexToHash("0x22222222222"), chunkIdx: 2222}, + args{encodingKey: common.HexToHash("0x22222222222"), sampleIdx: 2222}, "13571350061658342048390665596699168162893949286891081722317471185110722978977", false, }, { "test chunk 4095", - args{encodingKey: common.HexToHash("0x1e88fb83944b20562a100533d0521b90bf7df7cc6e0aaa1c46482b67c7b370ab"), chunkIdx: 4095}, + args{encodingKey: common.HexToHash("0x1e88fb83944b20562a100533d0521b90bf7df7cc6e0aaa1c46482b67c7b370ab"), sampleIdx: 4095}, "12199007973319674300030596965685270475268514105269206407619072166392043015767", false, }, } libDir := filepath.Join(proverPath, prover.SnarkLib) - p, err := prover.NewZKProver(libDir, zkeyFile, prover.WasmName, lg) + p, err := prover.NewZKProver(libDir, zkeyName, prover.WasmName, lg) if err != nil { t.Fatal(err) } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - maskGo, err := GenerateMask(tt.args.encodingKey, tt.args.chunkIdx) + inputBytes, err := p.GenerateInput(tt.args.encodingKey, tt.args.sampleIdx) + if err != nil { + t.Errorf("ZKProver.GenerateInput() error = %v", err) + return + } + var inputs map[string]interface{} + err = json.Unmarshal(inputBytes, &inputs) + if err != nil { + t.Errorf("ZKProver.GenerateInput() error = %v", err) + return + } + intputStr, ok := inputs["xIn"].(string) + if !ok { + t.Errorf("ZKProver.GenerateInput() type: %v, want string", reflect.TypeOf(inputs["xIn"])) + return + } + if intputStr != tt.xIn { + t.Errorf("ZKProver.GenerateInput() xIn = %v, want %v", inputs["xIn"], tt.xIn) + return + } + maskGo, err := GenerateMask(tt.args.encodingKey, tt.args.sampleIdx) if (err != nil) != tt.wantErr { t.Errorf("GenerateMask() error = %v, wantErr %v", err, tt.wantErr) return } - proofRaw, mask, err := p.GenerateZKProofPerSample(tt.args.encodingKey, tt.args.chunkIdx) + proofRaw, mask, err := p.GenerateZKProofPerSample(tt.args.encodingKey, tt.args.sampleIdx) if (err != nil) != tt.wantErr { t.Errorf("ZKProver.GenerateZKProofPerSample() error = %v, wantErr %v", err, tt.wantErr) return @@ -86,7 +108,7 @@ func TestZKProver_GenerateZKProofPerSample(t *testing.T) { t.Errorf("ZKProver.GenerateZKProofPerSample() mask = %v, GenerateMask %v", mask, maskGo) return } - err = verifyDecodeSample(proofRaw, tt.args.chunkIdx, tt.args.encodingKey, mask) + err = verifyDecodeSample(proofRaw, tt.args.sampleIdx, tt.args.encodingKey, mask) if (err != nil) != tt.wantErr { t.Errorf("ZKProver.GenerateZKProofPerSample() verifyDecodeSample err: %v", err) return @@ -158,8 +180,14 @@ func verifyDecodeSample(proofBytes []byte, trunkIdx uint64, encodingKey common.H return callVerify(calldata, common.HexToAddress(l1ContractV1)) } -func parseProof(data []byte) prover.ZKProof { - zkProof := prover.ZKProof{} +type ZKProof struct { + A prover.G1Point `json:"A"` + B prover.G2Point `json:"B"` + C prover.G1Point `json:"C"` +} + +func parseProof(data []byte) ZKProof { + zkProof := ZKProof{} x1 := new(big.Int).SetBytes(data[:32]) y1 := new(big.Int).SetBytes(data[32:64]) zkProof.A = prover.G1Point{X: x1, Y: y1} From d0582da1cda954f928f261d1d959468d4ee502b7 Mon Sep 17 00:00:00 2001 From: syntrust Date: Tue, 9 Jan 2024 18:49:03 +0800 Subject: [PATCH 07/45] minor --- ethstorage/miner/worker.go | 2 +- ethstorage/prover/zk_prover.go | 2 +- integration_tests/kzg_prover_test.go | 4 ++-- integration_tests/zk_prover_test.go | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ethstorage/miner/worker.go b/ethstorage/miner/worker.go index 883ab1d2..0a7fa45f 100644 --- a/ethstorage/miner/worker.go +++ b/ethstorage/miner/worker.go @@ -242,7 +242,7 @@ func (w *worker) updateDifficulty(shardIdx, blockTime uint64) (*big.Int, error) w.lg.Warn("Failed to get es mining info", "error", err.Error()) return nil, err } - w.lg.Info("Mining info retrieved", "shard", shardIdx, "LastMineTime", info.LastMineTime, "Difficulty", info.Difficulty, "proofsSubmitted", info.BlockMined) + w.lg.Info("Mining info retrieved", "shard", shardIdx, "lastMineTime", info.LastMineTime, "difficulty", info.Difficulty, "proofsSubmitted", info.BlockMined) reqDiff := new(big.Int).Div(maxUint256, expectedDiff( info.LastMineTime, blockTime, diff --git a/ethstorage/prover/zk_prover.go b/ethstorage/prover/zk_prover.go index 7510a5f3..c24487d4 100644 --- a/ethstorage/prover/zk_prover.go +++ b/ethstorage/prover/zk_prover.go @@ -56,7 +56,7 @@ func NewZKProver(libDir, zkeyName, wasmName string, lg log.Logger) (*ZKProver, e func (p *ZKProver) GenerateZKProofPerSample(encodingKey common.Hash, sampleIdx uint64) ([]byte, *big.Int, error) { p.lg.Debug("Generate zk proof", "encodingKey", encodingKey.Hex(), "sampleIdx", sampleIdx) if int(sampleIdx) >= eth.FieldElementsPerBlob { - return nil, nil, fmt.Errorf("chunk index out of scope: %d", sampleIdx) + return nil, nil, fmt.Errorf("sample index out of scope: %d", sampleIdx) } start := time.Now() defer func(start time.Time) { diff --git a/integration_tests/kzg_prover_test.go b/integration_tests/kzg_prover_test.go index dc88b8c8..41cab3a0 100644 --- a/integration_tests/kzg_prover_test.go +++ b/integration_tests/kzg_prover_test.go @@ -157,10 +157,10 @@ func uploadBlob(t *testing.T, data []byte) common.Hash { return dataHash } -func verifyInclusive(trunkIdx uint64, peInput []byte) error { +func verifyInclusive(sampleIdx uint64, peInput []byte) error { dataHash := common.Hash{} copy(dataHash[:], peInput[:24]) - index := new(big.Int).SetInt64(int64(trunkIdx)) + index := new(big.Int).SetInt64(int64(sampleIdx)) decodedData := new(big.Int).SetBytes(peInput[64:96]) h := crypto.Keccak256Hash([]byte("checkInclusive(bytes32,uint256,uint256,bytes)")) mid := h[0:4] diff --git a/integration_tests/zk_prover_test.go b/integration_tests/zk_prover_test.go index 17af4038..ed778aa5 100644 --- a/integration_tests/zk_prover_test.go +++ b/integration_tests/zk_prover_test.go @@ -132,7 +132,7 @@ func GenerateMask(encodingKey common.Hash, chunkIdx uint64) (*big.Int, error) { return new(big.Int).SetBytes(mask), nil } -func verifyDecodeSample(proofBytes []byte, trunkIdx uint64, encodingKey common.Hash, mask *big.Int) error { +func verifyDecodeSample(proofBytes []byte, sampleIdx uint64, encodingKey common.Hash, mask *big.Int) error { ctx := context.Background() client, err := ethclient.DialContext(ctx, l1Endpoint) if err != nil { @@ -141,7 +141,7 @@ func verifyDecodeSample(proofBytes []byte, trunkIdx uint64, encodingKey common.H defer client.Close() encodingKeyBN := new(big.Int).SetBytes(encodingKey[:]) - indexBN := new(big.Int).SetInt64(int64(trunkIdx)) + indexBN := new(big.Int).SetInt64(int64(sampleIdx)) h := crypto.Keccak256Hash([]byte("decodeSample(((uint256,uint256),(uint256[2],uint256[2]),(uint256,uint256)),uint256,uint256,uint256)")) uintType, _ := abi.NewType("uint256", "", nil) proofType, _ := abi.NewType("tuple", "", []abi.ArgumentMarshaling{ From 9c9d54c55a990ffdac452d06b05b9bceb0e71065 Mon Sep 17 00:00:00 2001 From: syntrust Date: Wed, 10 Jan 2024 14:55:14 +0800 Subject: [PATCH 08/45] engine test --- ethstorage/prover/zk_prover.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ethstorage/prover/zk_prover.go b/ethstorage/prover/zk_prover.go index c24487d4..a3383b6b 100644 --- a/ethstorage/prover/zk_prover.go +++ b/ethstorage/prover/zk_prover.go @@ -20,7 +20,9 @@ import ( "github.com/iden3/go-rapidsnark/prover" "github.com/iden3/go-rapidsnark/types" "github.com/iden3/go-rapidsnark/witness/v2" - "github.com/iden3/go-rapidsnark/witness/wazero" + + // "github.com/iden3/go-rapidsnark/witness/wazero" + "github.com/iden3/go-rapidsnark/witness/wasmer" ) type ZKProver struct { @@ -35,7 +37,7 @@ func NewZKProver(libDir, zkeyName, wasmName string, lg log.Logger) (*ZKProver, e lg.Error("Read wasm file failed", "error", err) return nil, err } - calc, err := witness.NewCalculator(wasmBytes, witness.WithWasmEngine(wazero.NewCircom2WZWitnessCalculator)) + calc, err := witness.NewCalculator(wasmBytes, witness.WithWasmEngine(wasmer.NewCircom2WitnessCalculator)) if err != nil { lg.Error("Create witness calculator failed", "error", err) return nil, err From c43964372960d124de7854a579160163d5845b60 Mon Sep 17 00:00:00 2001 From: syntrust Date: Wed, 10 Jan 2024 15:40:24 +0800 Subject: [PATCH 09/45] optimise --- Makefile | 2 +- ethstorage/prover/zk_prover.go | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index ed05c858..8bd4a95f 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ es-node: build cp -r ethstorage/prover/snark_lib build/bin build: - env GO111MODULE=on GOOS=$(TARGETOS) GOARCH=$(TARGETARCH) go build -v $(LDFLAGS) -o build/bin/es-node ./cmd/es-node/ + env GO111MODULE=on GOOS=$(TARGETOS) GOARCH=$(TARGETARCH) go build -v $(LDFLAGS) -o build/bin/es-node -tags rapidsnark_asm ./cmd/es-node/ clean: rm -r build diff --git a/ethstorage/prover/zk_prover.go b/ethstorage/prover/zk_prover.go index a3383b6b..c24487d4 100644 --- a/ethstorage/prover/zk_prover.go +++ b/ethstorage/prover/zk_prover.go @@ -20,9 +20,7 @@ import ( "github.com/iden3/go-rapidsnark/prover" "github.com/iden3/go-rapidsnark/types" "github.com/iden3/go-rapidsnark/witness/v2" - - // "github.com/iden3/go-rapidsnark/witness/wazero" - "github.com/iden3/go-rapidsnark/witness/wasmer" + "github.com/iden3/go-rapidsnark/witness/wazero" ) type ZKProver struct { @@ -37,7 +35,7 @@ func NewZKProver(libDir, zkeyName, wasmName string, lg log.Logger) (*ZKProver, e lg.Error("Read wasm file failed", "error", err) return nil, err } - calc, err := witness.NewCalculator(wasmBytes, witness.WithWasmEngine(wasmer.NewCircom2WitnessCalculator)) + calc, err := witness.NewCalculator(wasmBytes, witness.WithWasmEngine(wazero.NewCircom2WZWitnessCalculator)) if err != nil { lg.Error("Create witness calculator failed", "error", err) return nil, err From 08b4bbe1525c35b5c4f39a3fa888f8cf3659aabb Mon Sep 17 00:00:00 2001 From: syntrust Date: Wed, 10 Jan 2024 15:44:07 +0800 Subject: [PATCH 10/45] fix build --- go.mod | 7 +++---- go.sum | 2 ++ 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index bf34f95d..d2d62cd8 100644 --- a/go.mod +++ b/go.mod @@ -15,6 +15,8 @@ require ( github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d github.com/holiman/uint256 v1.2.3 github.com/iden3/go-iden3-crypto v0.0.15 + github.com/iden3/go-rapidsnark/types v0.0.3 + github.com/iden3/go-rapidsnark/witness/v2 v2.0.0 github.com/ipfs/go-datastore v0.6.0 github.com/libp2p/go-libp2p v0.32.0 github.com/libp2p/go-libp2p-pubsub v0.10.0 @@ -56,8 +58,6 @@ require ( github.com/hashicorp/golang-lru/arc/v2 v2.0.5 // indirect github.com/herumi/bls-eth-go-binary v1.28.1 // indirect github.com/huin/goupnp v1.3.0 // indirect - github.com/iden3/go-rapidsnark/types v0.0.3 // indirect - github.com/iden3/go-rapidsnark/witness/v2 v2.0.0 // indirect github.com/iden3/wasmer-go v0.0.1 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/kilic/bls12-381 v0.1.1-0.20220929213557-ca162e8a70f4 // indirect @@ -108,8 +108,7 @@ require ( github.com/hashicorp/go-multierror v1.1.1 github.com/hashicorp/golang-lru/v2 v2.0.5 github.com/iden3/go-rapidsnark/prover v0.0.10 - github.com/iden3/go-rapidsnark/witness/wasmer v0.0.0-20230524142950-0986cf057d4e - github.com/iden3/go-rapidsnark/witness/wazero v0.0.1 + github.com/iden3/go-rapidsnark/witness/wazero v0.0.0-20230524142950-0986cf057d4e github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/ipfs/go-cid v0.4.1 // indirect github.com/ipfs/go-ds-leveldb v0.5.0 diff --git a/go.sum b/go.sum index 91cb05d3..4d12257b 100644 --- a/go.sum +++ b/go.sum @@ -319,6 +319,8 @@ github.com/iden3/go-rapidsnark/witness/v2 v2.0.0 h1:mkY6VDfwKVJc83QGKmwVXY2LYepi github.com/iden3/go-rapidsnark/witness/v2 v2.0.0/go.mod h1:3JRjqUfW1hgI9hzLDO0v8z/DUkR0ZUehhYLlnIfRxnA= github.com/iden3/go-rapidsnark/witness/wasmer v0.0.0-20230524142950-0986cf057d4e h1:lqrevdLsG1k8ieaxgUQccf3unf73m3zmkHJ3oIdld90= github.com/iden3/go-rapidsnark/witness/wasmer v0.0.0-20230524142950-0986cf057d4e/go.mod h1:WUtPVKXrhfZHJXavwId2+8J/fKMHQ92N0MZDxt8sfEA= +github.com/iden3/go-rapidsnark/witness/wazero v0.0.0-20230524142950-0986cf057d4e h1:WeiFCrpj5pLRtSA4Mg03yTrSZhHHqN/k5b6bwxd9/tY= +github.com/iden3/go-rapidsnark/witness/wazero v0.0.0-20230524142950-0986cf057d4e/go.mod h1:UEBifEzw62T6VzIHJeHuUgeLg2U/J9ttf7hOwQEqnYk= github.com/iden3/go-rapidsnark/witness/wazero v0.0.1 h1:NSLCXVNWMSn+ilTCNUtIqbu9BViiICasq4FrMNCAds4= github.com/iden3/go-rapidsnark/witness/wazero v0.0.1/go.mod h1:UEBifEzw62T6VzIHJeHuUgeLg2U/J9ttf7hOwQEqnYk= github.com/iden3/wasmer-go v0.0.1 h1:TZKh8Se8B/73PvWrcu+FTU9L1k5XYAmtFbioj7l0Uog= From 4b3cd78a32756d59b0fea78b4b69c2816c9fcd86 Mon Sep 17 00:00:00 2001 From: syntrust Date: Wed, 10 Jan 2024 16:29:18 +0800 Subject: [PATCH 11/45] minor --- ethstorage/prover/kzg_poseidon_prover.go | 28 ++++++++++++------------ 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/ethstorage/prover/kzg_poseidon_prover.go b/ethstorage/prover/kzg_poseidon_prover.go index 14c3de87..48c4caf8 100644 --- a/ethstorage/prover/kzg_poseidon_prover.go +++ b/ethstorage/prover/kzg_poseidon_prover.go @@ -21,17 +21,17 @@ const ( ) type KZGPoseidonProver struct { - zkMode uint64 - libDir string - zkey string - lg log.Logger + zkProverMode uint64 + libDir string + zkey string + lg log.Logger } // Prover that can be used directly by miner to prove both KZG and Poseidon hash // workingDir specifies the working directory of the command relative to the caller. // zkeyFileName specifies the zkey file name to generate snark proof // returns a prover that can generate a combined KZG + zk proof -func NewKZGPoseidonProver(workingDir, zkeyFileName string, zkMode uint64, lg log.Logger) KZGPoseidonProver { +func NewKZGPoseidonProver(workingDir, zkeyFileName string, zkProverMode uint64, lg log.Logger) KZGPoseidonProver { // check dependencies when es-node starts libDir := filepath.Join(workingDir, SnarkLib) if _, err := os.Stat(libDir); errors.Is(err, os.ErrNotExist) { @@ -42,21 +42,21 @@ func NewKZGPoseidonProver(workingDir, zkeyFileName string, zkMode uint64, lg log lg.Crit("Init ZK prover failed", "error", "zkey does not exist", "dir", zkeyFile) } var wasmFile string - if zkMode == 2 { + if zkProverMode == 2 { wasmFile = filepath.Join(libDir, Wasm2Name) - } else if zkMode == 1 { + } else if zkProverMode == 1 { wasmFile = filepath.Join(libDir, WasmName) } else { - lg.Crit("Init ZK prover failed", "error", "invalid zkMode", "mode", zkMode) + lg.Crit("Init ZK prover failed", "error", "invalid zkProverMode", "mode", zkProverMode) } if _, err := os.Stat(zkeyFile); errors.Is(err, os.ErrNotExist) { lg.Crit("Init ZK prover failed", "error", "wasm does not exist", "dir", wasmFile) } return KZGPoseidonProver{ - zkMode: zkMode, - libDir: libDir, - zkey: zkeyFileName, - lg: lg, + zkProverMode: zkProverMode, + libDir: libDir, + zkey: zkeyFileName, + lg: lg, } } @@ -78,7 +78,7 @@ func (p *KZGPoseidonProver) GetStorageProof(data [][]byte, encodingKeys []common } var zkProofs [][]byte var masks []*big.Int - if p.zkMode == 1 { + if p.zkProverMode == 1 { prvr, err := NewZKProver(p.libDir, p.zkey, WasmName, p.lg) if err != nil { return nil, nil, nil, err @@ -91,7 +91,7 @@ func (p *KZGPoseidonProver) GetStorageProof(data [][]byte, encodingKeys []common zkProofs = append(zkProofs, zkProof) masks = append(masks, mask) } - } else if p.zkMode == 2 { + } else if p.zkProverMode == 2 { prvr, err := NewZKProver(p.libDir, p.zkey, Wasm2Name, p.lg) if err != nil { return nil, nil, nil, err From 592515350c4d07fa9902d4642e712d3293692613 Mon Sep 17 00:00:00 2001 From: syntrust Date: Wed, 10 Jan 2024 16:29:32 +0800 Subject: [PATCH 12/45] build docker --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 8b60f18e..c83593a6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ # Build ES node in a stock Go builder container FROM golang:1.21-alpine as builder -RUN apk add --no-cache gcc musl-dev linux-headers make +RUN apk add --no-cache gcc musl-dev linux-headers make build-essential libomp-dev ADD . /es-node WORKDIR /es-node RUN make @@ -8,7 +8,7 @@ RUN make # Pull ES node into a second stage deploy alpine container FROM alpine:latest COPY --from=builder /es-node/build/ /es-node/build/ -RUN apk add --no-cache curl grep +RUN apk add --no-cache curl grep libstdc++ gcompat libgomp # Entrypoint COPY --from=builder /es-node/run.sh /es-node/ From 331c0ab86bfc85124f9490500683d45c57a0409d Mon Sep 17 00:00:00 2001 From: syntrust Date: Wed, 10 Jan 2024 18:41:35 +0800 Subject: [PATCH 13/45] update docker --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index c83593a6..7b2aa228 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ # Build ES node in a stock Go builder container FROM golang:1.21-alpine as builder -RUN apk add --no-cache gcc musl-dev linux-headers make build-essential libomp-dev +RUN apk add --no-cache gcc musl-dev linux-headers make g++ ADD . /es-node WORKDIR /es-node RUN make From 9cbaeb767c5a4cbe6d2554ce7d452273ddf4434d Mon Sep 17 00:00:00 2001 From: syntrust Date: Thu, 11 Jan 2024 17:42:55 +0800 Subject: [PATCH 14/45] build docker for rapidsnark --- Dockerfile | 3 +-- Makefile | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 7b2aa228..a44595c4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,5 @@ # Build ES node in a stock Go builder container -FROM golang:1.21-alpine as builder -RUN apk add --no-cache gcc musl-dev linux-headers make g++ +FROM golang:1.21 as builder ADD . /es-node WORKDIR /es-node RUN make diff --git a/Makefile b/Makefile index 8bd4a95f..77ca566f 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ es-node: build cp -r ethstorage/prover/snark_lib build/bin build: - env GO111MODULE=on GOOS=$(TARGETOS) GOARCH=$(TARGETARCH) go build -v $(LDFLAGS) -o build/bin/es-node -tags rapidsnark_asm ./cmd/es-node/ + env GO111MODULE=on GOOS=$(TARGETOS) GOARCH=$(TARGETARCH) go build -v $(LDFLAGS) -o build/bin/es-node -tags rapidsnark_asm ./cmd/es-node/ clean: rm -r build From c555ec289c38e1bb6ecbd7c5b7068cf6aef8cee4 Mon Sep 17 00:00:00 2001 From: syntrust Date: Thu, 11 Jan 2024 17:43:25 +0800 Subject: [PATCH 15/45] fix wrong file name to check --- ethstorage/prover/kzg_poseidon_prover.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethstorage/prover/kzg_poseidon_prover.go b/ethstorage/prover/kzg_poseidon_prover.go index 48c4caf8..3c109c0e 100644 --- a/ethstorage/prover/kzg_poseidon_prover.go +++ b/ethstorage/prover/kzg_poseidon_prover.go @@ -49,7 +49,7 @@ func NewKZGPoseidonProver(workingDir, zkeyFileName string, zkProverMode uint64, } else { lg.Crit("Init ZK prover failed", "error", "invalid zkProverMode", "mode", zkProverMode) } - if _, err := os.Stat(zkeyFile); errors.Is(err, os.ErrNotExist) { + if _, err := os.Stat(wasmFile); errors.Is(err, os.ErrNotExist) { lg.Crit("Init ZK prover failed", "error", "wasm does not exist", "dir", wasmFile) } return KZGPoseidonProver{ From 653be0ba44a4f3e91a42e63ab4b42e5571f839e5 Mon Sep 17 00:00:00 2001 From: syntrust Date: Thu, 11 Jan 2024 17:56:59 +0800 Subject: [PATCH 16/45] boost zkp --- integration_tests/run_tests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration_tests/run_tests.sh b/integration_tests/run_tests.sh index 721ad9a5..f996193e 100755 --- a/integration_tests/run_tests.sh +++ b/integration_tests/run_tests.sh @@ -63,4 +63,4 @@ if [ ! -e ${zkey_file} ]; then rm cookie fi -go test -timeout 0 github.com/ethstorage/go-ethstorage/integration_tests -v +go test -tags rapidsnark_asm -timeout 0 github.com/ethstorage/go-ethstorage/integration_tests -v From a66163cf2e46cf320e609bb214e7d9dfb9aeed0f Mon Sep 17 00:00:00 2001 From: syntrust Date: Mon, 15 Jan 2024 12:00:32 +0800 Subject: [PATCH 17/45] replace folder name --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 836d1052..557ee7e4 100644 --- a/README.md +++ b/README.md @@ -83,8 +83,8 @@ The full list of options that you can use to configure an es-node are as follows |`--miner.priority-gas-price`|Priority gas price for mining transactions||| |`--miner.zk-prover-version value`|ZK prover version, 1: one proof per sample, 2: one proof for multiple samples|`2`|| |`--miner.threads-per-shard`|Number of threads per shard|`runtime.NumCPU() x 2`|| -|`--miner.zk-working-dir`|Path to the snarkjs folder|`build/bin`|| -|`--miner.zkey`|zkey file name which should be put in the snarkjs folder|`blob_poseidon2.zkey`|| +|`--miner.zk-working-dir`|Path to the snark_lib folder|`build/bin`|| +|`--miner.zkey`|zkey file name which should be put in the snark_lib folder|`blob_poseidon2.zkey`|| |`--miner.min-profit`|Minimum profit for mining transactions|`0`|| |`--network`|Predefined L1 network selection. Available networks: devnet||| |`--p2p.advertise.ip`|The IP address to advertise in Discv5, put into the ENR of the node. This may also be a hostname / domain name to resolve to an IP.||| From d8e8209363bd94cfb1ac0d410f24253c5486abdd Mon Sep 17 00:00:00 2001 From: syntrust Date: Wed, 31 Jan 2024 11:31:50 +0800 Subject: [PATCH 18/45] random key for blob --- integration_tests/kzg_prover_test.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/integration_tests/kzg_prover_test.go b/integration_tests/kzg_prover_test.go index 41cab3a0..353c5fa6 100644 --- a/integration_tests/kzg_prover_test.go +++ b/integration_tests/kzg_prover_test.go @@ -11,6 +11,7 @@ import ( "math/big" "os" "testing" + "time" "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi" @@ -98,7 +99,7 @@ func uploadBlob(t *testing.T, data []byte) common.Hash { if err != nil { t.Fatalf("Error getting nonce: %v", err) } - blbKey := "0x0000000000000000000000000000000000000000000000000000000000000001" + blbKey := crypto.Keccak256Hash(new(big.Int).SetInt64(time.Now().UnixNano()).Bytes()) blbIdx := common.Big0 length := new(big.Int).SetInt64(128 * 1024) @@ -111,7 +112,7 @@ func uploadBlob(t *testing.T, data []byte) common.Hash { {Type: uint256Type}, {Type: uint256Type}, } - values := []interface{}{common.HexToHash(blbKey), blbIdx, length} + values := []interface{}{blbKey, blbIdx, length} dataField, err := args.Pack(values...) if err != nil { t.Fatalf("Error getting calldata: %v", err) From 55cea85713db6e6fd8a65dad8bd89a1a8ae101cf Mon Sep 17 00:00:00 2001 From: syntrust Date: Wed, 31 Jan 2024 18:21:09 +0800 Subject: [PATCH 19/45] support zk imp flag --- Makefile | 1 + ethstorage/miner/cli.go | 12 +- ethstorage/miner/config.go | 2 + ethstorage/miner/miner_test.go | 3 +- ethstorage/node/node.go | 1 + ethstorage/prover/kzg_poseidon_prover.go | 55 ++- .../prover/snark_lib/generate_witness.js | 20 + .../prover/snark_lib/witness_calculator.js | 337 ++++++++++++++ ethstorage/prover/snarkbuild/.gitignore | 2 + ethstorage/prover/utils.go | 234 ++++++++++ ethstorage/prover/zk_prover.go | 412 +++++++++--------- ethstorage/prover/zk_prover2.go | 101 ----- ethstorage/prover/zk_prover_go.go | 183 ++++++++ integration_tests/node_mine_test.go | 9 +- integration_tests/zk_prover2_test.go | 89 ++-- integration_tests/zk_prover_test.go | 106 ++--- 16 files changed, 1147 insertions(+), 420 deletions(-) create mode 100644 ethstorage/prover/snark_lib/generate_witness.js create mode 100644 ethstorage/prover/snark_lib/witness_calculator.js create mode 100644 ethstorage/prover/snarkbuild/.gitignore create mode 100644 ethstorage/prover/utils.go delete mode 100644 ethstorage/prover/zk_prover2.go create mode 100644 ethstorage/prover/zk_prover_go.go diff --git a/Makefile b/Makefile index 77ca566f..62c8969a 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,7 @@ LDFLAGS := -ldflags "$(LDFLAGSSTRING)" es-node: build cp -r ethstorage/prover/snark_lib build/bin + mkdir -p build/bin/snarkbuild build: env GO111MODULE=on GOOS=$(TARGETOS) GOARCH=$(TARGETARCH) go build -v $(LDFLAGS) -o build/bin/es-node -tags rapidsnark_asm ./cmd/es-node/ diff --git a/ethstorage/miner/cli.go b/ethstorage/miner/cli.go index 30089f44..2e28f2c3 100644 --- a/ethstorage/miner/cli.go +++ b/ethstorage/miner/cli.go @@ -22,6 +22,7 @@ const ( ZKeyFileNameFlagName = "miner.zkey" ZKWorkingDirFlagName = "miner.zk-working-dir" ZKProverModeFlagName = "miner.zk-prover-mode" + ZKProverImpFlagName = "miner.zk-prover-imp" ThreadsPerShardFlagName = "miner.threads-per-shard" MinimumProfitFlagName = "miner.min-profit" ) @@ -66,10 +67,16 @@ func CLIFlags(envPrefix string) []cli.Flag { }, cli.Uint64Flag{ Name: ZKProverModeFlagName, - Usage: "ZK prover mode, 1: one proof per sample, 2: one proof for multiple samples. Default: 2", + Usage: "ZK prover mode, 1: one proof per sample, 2: one proof for multiple samples", Value: DefaultConfig.ZKProverMode, EnvVar: rollup.PrefixEnvVar(envPrefix, "ZK_PROVER_Mode"), }, + cli.Uint64Flag{ + Name: ZKProverImpFlagName, + Usage: "ZK prover implementation, 1: snarkjs, 2: go-rapidsnark", + Value: DefaultConfig.ZKProverImp, + EnvVar: rollup.PrefixEnvVar(envPrefix, "ZK_PROVER_IMP"), + }, cli.Uint64Flag{ Name: ThreadsPerShardFlagName, Usage: "Number of threads per shard", @@ -88,6 +95,7 @@ type CLIConfig struct { ZKeyFileName string ZKWorkingDir string ZKProverMode uint64 + ZKProverImp uint64 ThreadsPerShard uint64 } @@ -117,6 +125,7 @@ func (c CLIConfig) ToMinerConfig() (Config, error) { cfg.MinimumProfit = c.MinimumProfit cfg.ZKeyFileName = c.ZKeyFileName cfg.ZKProverMode = c.ZKProverMode + cfg.ZKProverImp = c.ZKProverImp cfg.ThreadsPerShard = c.ThreadsPerShard return cfg, nil } @@ -130,6 +139,7 @@ func ReadCLIConfig(ctx *cli.Context) CLIConfig { ZKeyFileName: ctx.GlobalString(ZKeyFileNameFlagName), ZKWorkingDir: ctx.GlobalString(ZKWorkingDirFlagName), ZKProverMode: ctx.GlobalUint64(ZKProverModeFlagName), + ZKProverImp: ctx.GlobalUint64(ZKProverImpFlagName), ThreadsPerShard: ctx.GlobalUint64(ThreadsPerShardFlagName), } return cfg diff --git a/ethstorage/miner/config.go b/ethstorage/miner/config.go index 8b8e4575..1d7799fd 100644 --- a/ethstorage/miner/config.go +++ b/ethstorage/miner/config.go @@ -32,6 +32,7 @@ type Config struct { ZKeyFileName string ZKWorkingDir string ZKProverMode uint64 + ZKProverImp uint64 ThreadsPerShard uint64 SignerFnFactory signer.SignerFactory SignerAddr common.Address @@ -50,6 +51,7 @@ var DefaultConfig = Config{ ZKeyFileName: "blob_poseidon2.zkey", ZKWorkingDir: filepath.Join("build", "bin"), ZKProverMode: 2, + ZKProverImp: 1, ThreadsPerShard: uint64(2 * runtime.NumCPU()), MinimumProfit: common.Big0, } diff --git a/ethstorage/miner/miner_test.go b/ethstorage/miner/miner_test.go index 83a15d59..75be12b7 100644 --- a/ethstorage/miner/miner_test.go +++ b/ethstorage/miner/miner_test.go @@ -61,11 +61,12 @@ func newMiner(t *testing.T, storageMgr *es.StorageManager, client *eth.PollingCl PriorityGasPrice: new(big.Int).SetUint64(10), ThreadsPerShard: 1, ZKProverMode: 2, + ZKProverImp: 1, ZKeyFileName: "blob_poseidon2.zkey", } l1api := NewL1MiningAPI(client, lg) zkWorkingDir, _ := filepath.Abs("../prover") - pvr := prover.NewKZGPoseidonProver(zkWorkingDir, defaultConfig.ZKeyFileName, defaultConfig.ZKProverMode, lg) + pvr := prover.NewKZGPoseidonProver(zkWorkingDir, defaultConfig.ZKeyFileName, defaultConfig.ZKProverMode, defaultConfig.ZKProverImp, lg) fd := new(event.Feed) miner := New(defaultConfig, storageMgr, l1api, &pvr, fd, lg) return miner diff --git a/ethstorage/node/node.go b/ethstorage/node/node.go index 1f6c12c4..37b7a473 100644 --- a/ethstorage/node/node.go +++ b/ethstorage/node/node.go @@ -252,6 +252,7 @@ func (n *EsNode) initMiner(ctx context.Context, cfg *Config) error { cfg.Mining.ZKWorkingDir, cfg.Mining.ZKeyFileName, cfg.Mining.ZKProverMode, + cfg.Mining.ZKProverImp, n.log, ) n.miner = miner.New(cfg.Mining, n.storageManager, l1api, &pvr, n.feed, n.log) diff --git a/ethstorage/prover/kzg_poseidon_prover.go b/ethstorage/prover/kzg_poseidon_prover.go index 3c109c0e..ba333ead 100644 --- a/ethstorage/prover/kzg_poseidon_prover.go +++ b/ethstorage/prover/kzg_poseidon_prover.go @@ -14,6 +14,19 @@ import ( "github.com/ethereum/go-ethereum/log" ) +type IZKProver interface { + // Generate a zk proof for the given encoding keys and samples and return proof and masks (mode 2) + GenerateZKProof(encodingKeys []common.Hash, sampleIdxs []uint64) ([]byte, []*big.Int, error) + // Generate public inputs (mode 2) + GenerateInputs(encodingKeys []common.Hash, sampleIdxs []uint64) ([]byte, error) + // Generate a zk proof for a given sample (mode 1) + GenerateZKProofPerSample(encodingKey common.Hash, sampleIdx uint64) ([]byte, *big.Int, error) + // Generate public input (mode 1) + GenerateInput(encodingKey common.Hash, sampleIdx uint64) ([]byte, error) + // Generate ZK Proof for the given encoding keys and samples and return proof and all publics (mode 2) + GenerateZKProofRaw(encodingKeys []common.Hash, sampleIdxs []uint64) ([]byte, []*big.Int, error) +} + const ( SnarkLib = "snark_lib" WasmName = "blob_poseidon.wasm" @@ -22,6 +35,7 @@ const ( type KZGPoseidonProver struct { zkProverMode uint64 + zkProverImp uint64 libDir string zkey string lg log.Logger @@ -30,8 +44,16 @@ type KZGPoseidonProver struct { // Prover that can be used directly by miner to prove both KZG and Poseidon hash // workingDir specifies the working directory of the command relative to the caller. // zkeyFileName specifies the zkey file name to generate snark proof +// zkProverMode specifies the mode of the zk prover, 1 for per sample, 2 for samples +// zkProverImp specifies the implementation of the zk prover, 1 for snarkjs, 2 for go-rapidsnark +// lg specifies the logger to log the info +// returns a prover that can generate a combined KZG + zk proof +func NewKZGPoseidonProverWithLogger(workingDir, zkeyFileName string, zkProverMode, zkProverImp uint64, lg log.Logger) KZGPoseidonProver { + return NewKZGPoseidonProver(workingDir, zkeyFileName, zkProverMode, zkProverImp, lg) +} + // returns a prover that can generate a combined KZG + zk proof -func NewKZGPoseidonProver(workingDir, zkeyFileName string, zkProverMode uint64, lg log.Logger) KZGPoseidonProver { +func NewKZGPoseidonProver(workingDir, zkeyFileName string, zkProverMode, zkProverImp uint64, lg log.Logger) KZGPoseidonProver { // check dependencies when es-node starts libDir := filepath.Join(workingDir, SnarkLib) if _, err := os.Stat(libDir); errors.Is(err, os.ErrNotExist) { @@ -54,6 +76,7 @@ func NewKZGPoseidonProver(workingDir, zkeyFileName string, zkProverMode uint64, } return KZGPoseidonProver{ zkProverMode: zkProverMode, + zkProverImp: zkProverImp, libDir: libDir, zkey: zkeyFileName, lg: lg, @@ -76,13 +99,13 @@ func (p *KZGPoseidonProver) GetStorageProof(data [][]byte, encodingKeys []common } peInputs = append(peInputs, peInput) } + prvr, err := p.getZKProver() + if err != nil { + return nil, nil, nil, err + } var zkProofs [][]byte var masks []*big.Int if p.zkProverMode == 1 { - prvr, err := NewZKProver(p.libDir, p.zkey, WasmName, p.lg) - if err != nil { - return nil, nil, nil, err - } for i, encodingKey := range encodingKeys { zkProof, mask, err := prvr.GenerateZKProofPerSample(encodingKey, sampleIdxInKv[i]) if err != nil { @@ -92,10 +115,6 @@ func (p *KZGPoseidonProver) GetStorageProof(data [][]byte, encodingKeys []common masks = append(masks, mask) } } else if p.zkProverMode == 2 { - prvr, err := NewZKProver(p.libDir, p.zkey, Wasm2Name, p.lg) - if err != nil { - return nil, nil, nil, err - } zkProof, msks, err := prvr.GenerateZKProof(encodingKeys, sampleIdxInKv) if err != nil { return nil, nil, nil, err @@ -107,3 +126,21 @@ func (p *KZGPoseidonProver) GetStorageProof(data [][]byte, encodingKeys []common } return masks, zkProofs, peInputs, nil } + +func (p *KZGPoseidonProver) getZKProver() (IZKProver, error) { + var wasm string + if p.zkProverMode == 2 { + wasm = WasmName + } else if p.zkProverMode == 1 { + wasm = WasmName + } else { + return nil, fmt.Errorf("invalid zk proof mode") + } + if p.zkProverImp == 1 { + return NewZKProver(filepath.Dir(p.libDir), p.zkey, wasm, p.lg), nil + } + if p.zkProverImp == 2 { + return NewZKProverGo(p.libDir, p.zkey, wasm, p.lg) + } + return nil, fmt.Errorf("invalid zk prover implementation: %d", p.zkProverImp) +} diff --git a/ethstorage/prover/snark_lib/generate_witness.js b/ethstorage/prover/snark_lib/generate_witness.js new file mode 100644 index 00000000..14095f16 --- /dev/null +++ b/ethstorage/prover/snark_lib/generate_witness.js @@ -0,0 +1,20 @@ +const wc = require("./witness_calculator.js"); +const { readFileSync, writeFile } = require("fs"); + +if (process.argv.length != 5) { + console.log("Usage: node generate_witness.js "); +} else { + const input = JSON.parse(readFileSync(process.argv[3], "utf8")); + + const buffer = readFileSync(process.argv[2]); + wc(buffer).then(async witnessCalculator => { + // const w= await witnessCalculator.calculateWitness(input,0); + // for (let i=0; i< w.length; i++){ + // console.log(w[i]); + // } + const buff= await witnessCalculator.calculateWTNSBin(input,0); + writeFile(process.argv[4], buff, function(err) { + if (err) throw err; + }); + }); +} \ No newline at end of file diff --git a/ethstorage/prover/snark_lib/witness_calculator.js b/ethstorage/prover/snark_lib/witness_calculator.js new file mode 100644 index 00000000..cc7dacd0 --- /dev/null +++ b/ethstorage/prover/snark_lib/witness_calculator.js @@ -0,0 +1,337 @@ +module.exports = async function builder(code, options) { + + options = options || {}; + + let wasmModule; + try { + wasmModule = await WebAssembly.compile(code); + } catch (err) { + console.log(err); + console.log("\nTry to run circom --c in order to generate c++ code instead\n"); + throw new Error(err); + } + + let wc; + + let errStr = ""; + let msgStr = ""; + + const instance = await WebAssembly.instantiate(wasmModule, { + runtime: { + exceptionHandler : function(code) { + let err; + if (code == 1) { + err = "Signal not found.\n"; + } else if (code == 2) { + err = "Too many signals set.\n"; + } else if (code == 3) { + err = "Signal already set.\n"; + } else if (code == 4) { + err = "Assert Failed.\n"; + } else if (code == 5) { + err = "Not enough memory.\n"; + } else if (code == 6) { + err = "Input signal array access exceeds the size.\n"; + } else { + err = "Unknown error.\n"; + } + throw new Error(err + errStr); + }, + printErrorMessage : function() { + errStr += getMessage() + "\n"; + // console.error(getMessage()); + }, + writeBufferMessage : function() { + const msg = getMessage(); + // Any calls to `log()` will always end with a `\n`, so that's when we print and reset + if (msg === "\n") { + console.log(msgStr); + msgStr = ""; + } else { + // If we've buffered other content, put a space in between the items + if (msgStr !== "") { + msgStr += " " + } + // Then append the message to the message we are creating + msgStr += msg; + } + }, + showSharedRWMemory : function() { + printSharedRWMemory (); + } + + } + }); + + const sanityCheck = + options +// options && +// ( +// options.sanityCheck || +// options.logGetSignal || +// options.logSetSignal || +// options.logStartComponent || +// options.logFinishComponent +// ); + + + wc = new WitnessCalculator(instance, sanityCheck); + return wc; + + function getMessage() { + var message = ""; + var c = instance.exports.getMessageChar(); + while ( c != 0 ) { + message += String.fromCharCode(c); + c = instance.exports.getMessageChar(); + } + return message; + } + + function printSharedRWMemory () { + const shared_rw_memory_size = instance.exports.getFieldNumLen32(); + const arr = new Uint32Array(shared_rw_memory_size); + for (let j=0; j { + const h = fnvHash(k); + const hMSB = parseInt(h.slice(0,8), 16); + const hLSB = parseInt(h.slice(8,16), 16); + const fArr = flatArray(input[k]); + let signalSize = this.instance.exports.getInputSignalSize(hMSB, hLSB); + if (signalSize < 0){ + throw new Error(`Signal ${k} not found\n`); + } + if (fArr.length < signalSize) { + throw new Error(`Not enough values for input signal ${k}\n`); + } + if (fArr.length > signalSize) { + throw new Error(`Too many values for input signal ${k}\n`); + } + for (let i=0; i0) { + res.unshift(0); + i--; + } + } + return res; +} + +function fromArray32(arr) { //returns a BigInt + var res = BigInt(0); + const radix = BigInt(0x100000000); + for (let i = 0; i= eth.FieldElementsPerBlob { - return nil, nil, fmt.Errorf("sample index out of scope: %d", sampleIdx) +func (p *ZKProver) GenerateZKProofRaw(encodingKeys []common.Hash, sampleIdxs []uint64) ([]byte, []*big.Int, error) { + for i, idx := range sampleIdxs { + p.lg.Debug("Generate zk proof", "encodingKey", encodingKeys[i], "sampleIdx", sampleIdxs[i]) + if int(idx) >= eth.FieldElementsPerBlob { + return nil, nil, fmt.Errorf("chunk index out of scope: %d", idx) + } } start := time.Now() defer func(start time.Time) { dur := time.Since(start) - p.lg.Info("Generate zk proof", "sampleIdx", sampleIdx, "timeUsed(s)", dur.Seconds()) + p.lg.Info("Generate zk proof done", "sampleIdx", sampleIdxs, "took(sec)", dur.Seconds()) }(start) - inputBytes, err := p.GenerateInput(encodingKey, sampleIdx) + tempDir := crypto.Keccak256Hash([]byte(fmt.Sprint(encodingKeys, sampleIdxs))) + p.lg.Debug("Generate zk proof", "path", common.Bytes2Hex(tempDir[:])) + buildDir := filepath.Join(p.dir, snarkBuildDir, common.Bytes2Hex(tempDir[:])) + if _, err := os.Stat(buildDir); err == nil { + os.RemoveAll(buildDir) + } + err := os.Mkdir(buildDir, os.ModePerm) if err != nil { - p.lg.Error("Generate inputs failed", "error", err) + p.lg.Error("Generate zk proof failed", "mkdir", buildDir, "error", err) return nil, nil, err } - proof, publicInputs, err := p.prove(inputBytes) + libDir := filepath.Join(p.dir, SnarkLib) + + // 1. Generate input + inputs, err := p.GenerateInputs(encodingKeys, sampleIdxs) if err != nil { - p.lg.Error("Prove failed", "error", err) + p.lg.Error("Generate inputs failed", "error", err) return nil, nil, err } - mask, err := readMask(publicInputs) + inputFile := filepath.Join(buildDir, inputName) + err = os.WriteFile(inputFile, inputs, 0644) if err != nil { + fmt.Println("Unable to write file:", err) return nil, nil, err } - p.lg.Debug("Generate zk proof", "mask", mask) - return proof, mask, nil -} -func (p *ZKProver) GenerateInput(encodingKey common.Hash, sampleIdx uint64) ([]byte, error) { - var b fr.Element - var exp big.Int - exp.Div(exp.Sub(fr.Modulus(), common.Big1), big.NewInt(int64(eth.FieldElementsPerBlob))) - ru := b.Exp(*b.SetInt64(5), &exp) - xIn := ru.Exp(*ru, big.NewInt(int64(sampleIdx))) - encodingKeyMod := fr.Modulus().Mod(encodingKey.Big(), fr.Modulus()) - inputObj := InputPair{ - EncodingKeyIn: hexutil.Encode(encodingKeyMod.Bytes()), - XIn: xIn.String(), - } - p.lg.Debug("Generate zk proof", "input", inputObj) - return json.Marshal(inputObj) -} - -func (p *ZKProver) prove(inputBytes []byte) ([]byte, string, error) { - parsedInputs, err := witness.ParseInputs(inputBytes) + // 2. Generate witness + wtnsFile := filepath.Join(buildDir, witnessName) + cmd := exec.Command("node", + filepath.Join(libDir, witnessGenerator), + filepath.Join(libDir, p.wasmName), + inputFile, + wtnsFile, + ) + cmd.Dir = libDir + out, err := cmd.Output() if err != nil { - p.lg.Error("Parse input failed", "error", err) - return nil, "", err + p.lg.Error("Generate witness failed", "error", err, "cmd", cmd.String(), "output", string(out)) + return nil, nil, err } - wtnsBytes, err := p.calc.CalculateWTNSBin(parsedInputs, true) + p.lg.Debug("Generate witness done") + + // 3. Generate proof + proofFile := filepath.Join(buildDir, proofName) + publicFile := filepath.Join(buildDir, publicName) + cmd = exec.Command("snarkjs", "groth16", "prove", + filepath.Join(libDir, p.zkeyName), + wtnsFile, + proofFile, + publicFile, + ) + cmd.Dir = libDir + out, err = cmd.Output() if err != nil { - p.lg.Error("Calculate witness failed", "error", err) - return nil, "", err + p.lg.Error("Generate proof failed", "error", err, "cmd", cmd.String(), "output", string(out)) + return nil, nil, err } - proofRaw, publicInputs, err := prover.Groth16ProverRaw(p.zkey, wtnsBytes) + p.lg.Debug("Generate proof done") + + // 4. Read proof and masks + proof, err := readProofFrom(proofFile) if err != nil { - p.lg.Error("Prove failed", "error", err) - return nil, "", err + p.lg.Error("Parse proof failed", "error", err) + return nil, nil, err } - p.lg.Debug("Generate zk proof", "publicInputs", publicInputs) - proof, err := readProof(proofRaw) + publics, err := readPublicsFrom(publicFile) if err != nil { - p.lg.Error("Read proof failed", "error", err) - return nil, "", err + p.lg.Error("Read publics failed", "error", err) + return nil, nil, err } - return proof, publicInputs, nil + return proof, publics, nil } -func readProof(proofRaw string) ([]byte, error) { - var piOut = types.ProofData{} - if err := json.Unmarshal([]byte(proofRaw), &piOut); err != nil { - return nil, err - } - u2, _ := abi.NewType("uint256[2]", "", nil) - u22, _ := abi.NewType("uint256[2][2]", "", nil) - args := abi.Arguments{ - {Type: u2}, - {Type: u22}, - {Type: u2}, - } - a, err := toG1Point(piOut.A[:2]) - if err != nil { - return nil, err - } - b, err := toG2Point(piOut.B[0:2]) - if err != nil { - return nil, err - } - c, err := toG1Point(piOut.C[0:2]) +func (p *ZKProver) GenerateInputs(encodingKeys []common.Hash, sampleIdxs []uint64) ([]byte, error) { + var encodingKeyModStr, xInStr []string + for i, sampleIdx := range sampleIdxs { + var b fr.Element + var exp big.Int + exp.Div(exp.Sub(fr.Modulus(), common.Big1), big.NewInt(int64(eth.FieldElementsPerBlob))) + ru := b.Exp(*b.SetInt64(5), &exp) + xIn := ru.Exp(*ru, new(big.Int).SetUint64(sampleIdx)) + xInStr = append(xInStr, xIn.String()) + encodingKeyMod := fr.Modulus().Mod(encodingKeys[i].Big(), fr.Modulus()) + encodingKeyModStr = append(encodingKeyModStr, hexutil.Encode(encodingKeyMod.Bytes())) + } + inputObj := InputPairV2{ + EncodingKeyIn: encodingKeyModStr, + XIn: xInStr, + } + inputs, err := json.Marshal(inputObj) if err != nil { + p.lg.Error("Encode input failed", "error", err) return nil, err } - values := []interface{}{[]*big.Int{a.X, a.Y}, [][]*big.Int{b.X[:], b.Y[:]}, []*big.Int{c.X, c.Y}} - packed, err := args.Pack(values...) - if err != nil { - return nil, fmt.Errorf("%v, values: %v", err, values) - } - return packed, nil + p.lg.Debug("Generate zk proof", "input", inputObj) + return inputs, nil } -func readMask(publicInputs string) (*big.Int, error) { - var output []string - if err := json.Unmarshal([]byte(publicInputs), &output); err != nil { - return nil, err - } - if len(output) != 3 { - return nil, fmt.Errorf("invalid public output") +// Generate ZK Proof for the given encoding key and chunck index using snarkjs +func (p *ZKProver) GenerateZKProofPerSample(encodingKey common.Hash, sampleIdx uint64) ([]byte, *big.Int, error) { + p.lg.Debug("Generate zk proof", "encodingKey", encodingKey.Hex(), "sampleIdx", sampleIdx) + if int(sampleIdx) >= eth.FieldElementsPerBlob { + return nil, nil, fmt.Errorf("chunk index out of scope: %d", sampleIdx) } - mask, ok := new(big.Int).SetString(output[2], 0) - if !ok { - return nil, fmt.Errorf("invalid mask") + start := time.Now() + defer func(start time.Time) { + dur := time.Since(start) + p.lg.Info("Generate zk proof", "sampleIdx", sampleIdx, "took(sec)", dur.Seconds()) + }(start) + buildDir := filepath.Join(p.dir, snarkBuildDir, strings.Join([]string{ + encodingKey.Hex(), + fmt.Sprint(sampleIdx), + }, "-")) + if _, err := os.Stat(buildDir); err == nil { + os.RemoveAll(buildDir) + } + err := os.Mkdir(buildDir, os.ModePerm) + if err != nil { + p.lg.Error("Generate zk proof failed", "mkdir", buildDir, "error", err) + return nil, nil, err } - return mask, nil -} - -type InputPair struct { - EncodingKeyIn string `json:"encodingKeyIn"` - XIn string `json:"xIn"` -} + libDir := filepath.Join(p.dir, SnarkLib) -func toG1Point(s []string) (G1Point, error) { - var x, y big.Int - _, ok := x.SetString(s[0], 10) - if !ok { - return G1Point{}, fmt.Errorf("invalid number %s", s[0]) + // 1. Generate input + input, err := p.GenerateInput(encodingKey, sampleIdx) + if err != nil { + p.lg.Error("Generate input failed", "error", err) + return nil, nil, err } - _, ok = y.SetString(s[1], 10) - if !ok { - return G1Point{}, fmt.Errorf("invalid number %s", s[1]) + inputFile := filepath.Join(buildDir, inputName) + err = os.WriteFile(inputFile, input, 0644) + if err != nil { + fmt.Println("Unable to write file:", err) + return nil, nil, err } - return G1Point{&x, &y}, nil -} -func toG2Point(s [][]string) (G2Point, error) { - var x, y [2]*big.Int - for i, vi := range s { - for j, vj := range vi { - z := new(big.Int) - _, ok := z.SetString(vj, 10) - if !ok { - return G2Point{}, fmt.Errorf("invalid number %s", vj) - } - // swap so that it can be accepted by the verifier contract - if i == 0 { - x[1-j] = z - } else { - y[1-j] = z - } - } + // 2. Generate witness + wtnsFile := filepath.Join(buildDir, witnessName) + cmd := exec.Command("node", + filepath.Join(libDir, witnessGenerator), + filepath.Join(libDir, p.wasmName), + inputFile, + wtnsFile, + ) + cmd.Dir = libDir + out, err := cmd.Output() + if err != nil { + p.lg.Error("Generate witness failed", "error", err, "cmd", cmd.String(), "output", string(out)) + return nil, nil, err } - return G2Point{x, y}, nil -} - -type G1Point struct { - X *big.Int - Y *big.Int -} - -func (p G1Point) MarshalJSON() ([]byte, error) { - return json.Marshal(&struct { - X string `json:"X"` - Y string `json:"Y"` - }{ - X: p.X.String(), - Y: p.Y.String(), - }) -} + p.lg.Debug("Generate witness done") -func (p *G1Point) UnmarshalJSON(b []byte) error { - var values struct { - X string `json:"X"` - Y string `json:"Y"` - } - err := json.Unmarshal(b, &values) + // 3. Generate proof + proofFile := filepath.Join(buildDir, proofName) + publicFile := filepath.Join(buildDir, publicName) + cmd = exec.Command("snarkjs", "groth16", "prove", + filepath.Join(libDir, p.zkeyName), + wtnsFile, + proofFile, + publicFile, + ) + cmd.Dir = libDir + out, err = cmd.Output() if err != nil { - fmt.Printf("Unmarshal %v\n", err) - return err + p.lg.Error("Generate proof failed", "error", err, "cmd", cmd.String(), "output", string(out)) + return nil, nil, err } - p.X = new(big.Int) - _, ok := p.X.SetString(values.X, 10) - if !ok { - return err + p.lg.Debug("Generate proof done") + + // 4. Read proof and mask + proof, err := readProofFrom(proofFile) + if err != nil { + p.lg.Error("Parse proof failed", "error", err) + return nil, nil, err } - p.Y = new(big.Int) - _, ok = p.Y.SetString(values.Y, 10) - if !ok { - return err + mask, err := readMaskFrom(publicFile) + if err != nil { + p.lg.Error("Read mask failed", "error", err) + return nil, nil, err } - return nil -} - -type G2Point struct { - X [2]*big.Int `json:"X"` - Y [2]*big.Int `json:"Y"` + return proof, mask, nil } -func (p *G2Point) UnmarshalJSON(b []byte) error { - var values struct { - X [2]string `json:"X"` - Y [2]string `json:"Y"` +func (p *ZKProver) GenerateInput(encodingKey common.Hash, sampleIdx uint64) ([]byte, error) { + var b fr.Element + var exp big.Int + exp.Div(exp.Sub(fr.Modulus(), common.Big1), big.NewInt(int64(eth.FieldElementsPerBlob))) + ru := b.Exp(*b.SetInt64(5), &exp) + xIn := ru.Exp(*ru, big.NewInt(int64(sampleIdx))) + encodingKeyMod := fr.Modulus().Mod(encodingKey.Big(), fr.Modulus()) + inputObj := InputPair{ + EncodingKeyIn: hexutil.Encode(encodingKeyMod.Bytes()), + XIn: xIn.String(), } - err := json.Unmarshal(b, &values) + input, err := json.Marshal(inputObj) if err != nil { - fmt.Printf("Unmarshal %v\n", err) - return err - } - for j, vj := range values.X { - z := new(big.Int) - _, ok := z.SetString(vj, 10) - if !ok { - return err - } - // swap so that it can be accepted by the verifier contract - p.X[1-j] = z - } - for j, vj := range values.Y { - z := new(big.Int) - _, ok := z.SetString(vj, 10) - if !ok { - return err - } - // swap so that it can be accepted by the verifier contract - p.Y[1-j] = z + p.lg.Error("Encode input failed", "error", err) + return nil, err } - return nil -} - -func (p G2Point) MarshalJSON() ([]byte, error) { - return json.Marshal(&struct { - X [2]string `json:"X"` - Y [2]string `json:"Y"` - }{ - X: [2]string{p.X[0].String(), p.X[1].String()}, - Y: [2]string{p.Y[0].String(), p.Y[1].String()}, - }) + p.lg.Debug("Generate zk proof", "input", inputObj) + return input, nil } diff --git a/ethstorage/prover/zk_prover2.go b/ethstorage/prover/zk_prover2.go deleted file mode 100644 index d6d63a8f..00000000 --- a/ethstorage/prover/zk_prover2.go +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright 2022-2023, EthStorage. -// For license information, see https://github.com/ethstorage/es-node/blob/main/LICENSE - -package prover - -import ( - "encoding/json" - "fmt" - "math/big" - "time" - - "github.com/consensys/gnark-crypto/ecc/bn254/fr" - "github.com/crate-crypto/go-proto-danksharding-crypto/eth" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" -) - -// Generate ZK Proof for the given encoding key and sample index -func (p *ZKProver) GenerateZKProof(encodingKeys []common.Hash, sampleIdxs []uint64) ([]byte, []*big.Int, error) { - proof, publics, err := p.GenerateZKProofRaw(encodingKeys, sampleIdxs) - if err != nil { - return nil, nil, err - } - if len(publics) != 6 { - return nil, nil, fmt.Errorf("publics length is %d", len(publics)) - } - return proof, publics[4:], nil -} - -// Generate ZK Proof for the given encoding keys and chunck indexes using snarkjs -func (p *ZKProver) GenerateZKProofRaw(encodingKeys []common.Hash, sampleIdxs []uint64) ([]byte, []*big.Int, error) { - for i, idx := range sampleIdxs { - p.lg.Debug("Generate zk proof", "encodingKey", encodingKeys[i], "sampleIdx", sampleIdxs[i]) - if int(idx) >= eth.FieldElementsPerBlob { - return nil, nil, fmt.Errorf("chunk index out of scope: %d", idx) - } - } - start := time.Now() - defer func(start time.Time) { - dur := time.Since(start) - p.lg.Info("Generate zk proof done", "sampleIdx", sampleIdxs, "timeUsed(s)", dur.Seconds()) - }(start) - - inputBytes, err := p.GenerateInputs(encodingKeys, sampleIdxs) - if err != nil { - p.lg.Error("Generate inputs failed", "error", err) - return nil, nil, err - } - proof, publicInputs, err := p.prove(inputBytes) - if err != nil { - p.lg.Error("Prove failed", "error", err) - return nil, nil, err - } - publics, err := readPublics(publicInputs) - if err != nil { - p.lg.Error("Read publics failed", "error", err) - return nil, nil, err - } - return proof, publics, nil -} - -func (p *ZKProver) GenerateInputs(encodingKeys []common.Hash, sampleIdxs []uint64) ([]byte, error) { - var encodingKeyModStr, xInStr []string - for i, sampleIdx := range sampleIdxs { - var b fr.Element - var exp big.Int - exp.Div(exp.Sub(fr.Modulus(), common.Big1), big.NewInt(int64(eth.FieldElementsPerBlob))) - ru := b.Exp(*b.SetInt64(5), &exp) - xIn := ru.Exp(*ru, new(big.Int).SetUint64(sampleIdx)) - xInStr = append(xInStr, xIn.String()) - encodingKeyMod := fr.Modulus().Mod(encodingKeys[i].Big(), fr.Modulus()) - encodingKeyModStr = append(encodingKeyModStr, hexutil.Encode(encodingKeyMod.Bytes())) - } - inputObj := InputPairV2{ - EncodingKeyIn: encodingKeyModStr, - XIn: xInStr, - } - p.lg.Debug("Generate zk proof", "input", inputObj) - return json.Marshal(inputObj) -} - -func readPublics(publicInputs string) ([]*big.Int, error) { - var output []string - if err := json.Unmarshal([]byte(publicInputs), &output); err != nil { - return nil, err - } - var publics []*big.Int - for _, v := range output { - pub, ok := new(big.Int).SetString(v, 0) - if !ok { - return nil, fmt.Errorf("invalid public input %v", v) - } - publics = append(publics, pub) - } - return publics, nil -} - -type InputPairV2 struct { - EncodingKeyIn []string `json:"encodingKeyIn"` - XIn []string `json:"xIn"` -} diff --git a/ethstorage/prover/zk_prover_go.go b/ethstorage/prover/zk_prover_go.go new file mode 100644 index 00000000..cc040463 --- /dev/null +++ b/ethstorage/prover/zk_prover_go.go @@ -0,0 +1,183 @@ +// Copyright 2022-2023, EthStorage. +// For license information, see https://github.com/ethstorage/es-node/blob/main/LICENSE + +package prover + +import ( + "encoding/json" + "fmt" + "math/big" + "os" + "path/filepath" + "time" + + "github.com/consensys/gnark-crypto/ecc/bn254/fr" + "github.com/crate-crypto/go-proto-danksharding-crypto/eth" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/log" + "github.com/iden3/go-rapidsnark/prover" + "github.com/iden3/go-rapidsnark/witness/v2" + "github.com/iden3/go-rapidsnark/witness/wazero" +) + +type ZKProverGo struct { + calc witness.Calculator + zkey []byte + lg log.Logger +} + +func NewZKProverGo(libDir, zkeyName, wasmName string, lg log.Logger) (*ZKProverGo, error) { + wasmBytes, err := os.ReadFile(filepath.Join(libDir, wasmName)) + if err != nil { + lg.Error("Read wasm file failed", "error", err) + return nil, err + } + calc, err := witness.NewCalculator(wasmBytes, witness.WithWasmEngine(wazero.NewCircom2WZWitnessCalculator)) + if err != nil { + lg.Error("Create witness calculator failed", "error", err) + return nil, err + } + zkey, err := os.ReadFile(filepath.Join(libDir, zkeyName)) + if err != nil { + lg.Error("Read zkey file failed", "error", err) + return nil, err + } + return &ZKProverGo{ + zkey: zkey, + calc: calc, + lg: lg, + }, nil +} + +// Generate ZK Proof for the given encoding key and sample index +func (p *ZKProverGo) GenerateZKProof(encodingKeys []common.Hash, sampleIdxs []uint64) ([]byte, []*big.Int, error) { + proof, publics, err := p.GenerateZKProofRaw(encodingKeys, sampleIdxs) + if err != nil { + return nil, nil, err + } + if len(publics) != 6 { + return nil, nil, fmt.Errorf("publics length is %d", len(publics)) + } + return proof, publics[4:], nil +} + +func (p *ZKProverGo) GenerateZKProofRaw(encodingKeys []common.Hash, sampleIdxs []uint64) ([]byte, []*big.Int, error) { + for i, idx := range sampleIdxs { + p.lg.Debug("Generate zk proof", "encodingKey", encodingKeys[i], "sampleIdx", sampleIdxs[i]) + if int(idx) >= eth.FieldElementsPerBlob { + return nil, nil, fmt.Errorf("chunk index out of scope: %d", idx) + } + } + start := time.Now() + defer func(start time.Time) { + dur := time.Since(start) + p.lg.Info("Generate zk proof done", "sampleIdx", sampleIdxs, "timeUsed(s)", dur.Seconds()) + }(start) + + inputBytes, err := p.GenerateInputs(encodingKeys, sampleIdxs) + if err != nil { + p.lg.Error("Generate inputs failed", "error", err) + return nil, nil, err + } + proof, publicInputs, err := p.prove(inputBytes) + if err != nil { + p.lg.Error("Prove failed", "error", err) + return nil, nil, err + } + publics, err := readPublics([]byte(publicInputs)) + if err != nil { + p.lg.Error("Read publics failed", "error", err) + return nil, nil, err + } + return proof, publics, nil +} + +func (p *ZKProverGo) GenerateInputs(encodingKeys []common.Hash, sampleIdxs []uint64) ([]byte, error) { + var encodingKeyModStr, xInStr []string + for i, sampleIdx := range sampleIdxs { + var b fr.Element + var exp big.Int + exp.Div(exp.Sub(fr.Modulus(), common.Big1), big.NewInt(int64(eth.FieldElementsPerBlob))) + ru := b.Exp(*b.SetInt64(5), &exp) + xIn := ru.Exp(*ru, new(big.Int).SetUint64(sampleIdx)) + xInStr = append(xInStr, xIn.String()) + encodingKeyMod := fr.Modulus().Mod(encodingKeys[i].Big(), fr.Modulus()) + encodingKeyModStr = append(encodingKeyModStr, hexutil.Encode(encodingKeyMod.Bytes())) + } + inputObj := InputPairV2{ + EncodingKeyIn: encodingKeyModStr, + XIn: xInStr, + } + p.lg.Debug("Generate zk proof", "input", inputObj) + return json.Marshal(inputObj) +} + +func (p *ZKProverGo) GenerateZKProofPerSample(encodingKey common.Hash, sampleIdx uint64) ([]byte, *big.Int, error) { + p.lg.Debug("Generate zk proof", "encodingKey", encodingKey.Hex(), "sampleIdx", sampleIdx) + if int(sampleIdx) >= eth.FieldElementsPerBlob { + return nil, nil, fmt.Errorf("sample index out of scope: %d", sampleIdx) + } + start := time.Now() + defer func(start time.Time) { + dur := time.Since(start) + p.lg.Info("Generate zk proof", "sampleIdx", sampleIdx, "timeUsed(s)", dur.Seconds()) + }(start) + + inputBytes, err := p.GenerateInput(encodingKey, sampleIdx) + if err != nil { + p.lg.Error("Generate inputs failed", "error", err) + return nil, nil, err + } + proof, publicInputs, err := p.prove(inputBytes) + if err != nil { + p.lg.Error("Prove failed", "error", err) + return nil, nil, err + } + mask, err := readMask([]byte(publicInputs)) + if err != nil { + return nil, nil, err + } + p.lg.Debug("Generate zk proof", "mask", mask) + return proof, mask, nil +} + +func (p *ZKProverGo) GenerateInput(encodingKey common.Hash, sampleIdx uint64) ([]byte, error) { + var b fr.Element + var exp big.Int + exp.Div(exp.Sub(fr.Modulus(), common.Big1), big.NewInt(int64(eth.FieldElementsPerBlob))) + ru := b.Exp(*b.SetInt64(5), &exp) + xIn := ru.Exp(*ru, big.NewInt(int64(sampleIdx))) + encodingKeyMod := fr.Modulus().Mod(encodingKey.Big(), fr.Modulus()) + inputObj := InputPair{ + EncodingKeyIn: hexutil.Encode(encodingKeyMod.Bytes()), + XIn: xIn.String(), + } + p.lg.Debug("Generate zk proof", "input", inputObj) + return json.Marshal(inputObj) +} + +func (p *ZKProverGo) prove(inputBytes []byte) ([]byte, string, error) { + parsedInputs, err := witness.ParseInputs(inputBytes) + if err != nil { + p.lg.Error("Parse input failed", "error", err) + return nil, "", err + } + wtnsBytes, err := p.calc.CalculateWTNSBin(parsedInputs, true) + if err != nil { + p.lg.Error("Calculate witness failed", "error", err) + return nil, "", err + } + proofRaw, publicInputs, err := prover.Groth16ProverRaw(p.zkey, wtnsBytes) + if err != nil { + p.lg.Error("Prove failed", "error", err) + return nil, "", err + } + p.lg.Debug("Generate zk proof", "publicInputs", publicInputs) + proof, err := readProof([]byte(proofRaw)) + if err != nil { + p.lg.Error("Read proof failed", "error", err) + return nil, "", err + } + return proof, publicInputs, nil +} diff --git a/integration_tests/node_mine_test.go b/integration_tests/node_mine_test.go index 4d1a88ee..91ce1e5a 100644 --- a/integration_tests/node_mine_test.go +++ b/integration_tests/node_mine_test.go @@ -74,7 +74,13 @@ func TestMining(t *testing.T) { feed := new(event.Feed) l1api := miner.NewL1MiningAPI(pClient, lg) - pvr := prover.NewKZGPoseidonProver(miningConfig.ZKWorkingDir, miningConfig.ZKeyFileName, 2, lg) + pvr := prover.NewKZGPoseidonProver( + miningConfig.ZKWorkingDir, + miningConfig.ZKeyFileName, + miningConfig.ZKProverMode, + miningConfig.ZKProverImp, + lg, + ) mnr := miner.New(miningConfig, storageManager, l1api, &pvr, feed, lg) lg.Info("Initialized miner") @@ -413,6 +419,7 @@ func initMiningConfig(t *testing.T, l1Contract common.Address, client *eth.Polli } miningConfig.ZKWorkingDir = proverPath miningConfig.ZKProverMode = 2 + miningConfig.ZKProverImp = 1 miningConfig.ThreadsPerShard = 2 miningConfig.MinimumProfit = new(big.Int).SetInt64(-1e18) return miningConfig diff --git a/integration_tests/zk_prover2_test.go b/integration_tests/zk_prover2_test.go index 364d3bb6..39b84f05 100644 --- a/integration_tests/zk_prover2_test.go +++ b/integration_tests/zk_prover2_test.go @@ -47,58 +47,63 @@ func TestZKProver_GenerateZKProof(t *testing.T) { "12199007973319674300030596965685270475268514105269206407619072166392043015767", } libDir := filepath.Join(proverPath, prover.SnarkLib) - p, err := prover.NewZKProver(libDir, zkey2Name, prover.Wasm2Name, lg) + pjs := prover.NewZKProver(proverPath, zkey2Name, prover.Wasm2Name, lg) + pgo, err := prover.NewZKProverGo(libDir, zkey2Name, prover.Wasm2Name, lg) if err != nil { - t.Errorf("NewZKProver() error = %v", err) + t.Errorf("NewZKProverGo() error = %v", err) return } - t.Run("zk test", func(t *testing.T) { - inputsBytes, err := p.GenerateInputs(encodingKeys, sampleIdxs) - if err != nil { - t.Errorf("ZKProver.GenerateInputs() error = %v", err) - return - } - var inputs map[string]interface{} - err = json.Unmarshal(inputsBytes, &inputs) - if err != nil { - t.Errorf("ZKProver.GenerateInputs() error = %v", err) - return - } - vxIn, ok := inputs["xIn"].([]interface{}) - if !ok { - t.Errorf("ZKProver.GenerateInputs() type: %v, want []interface{}", reflect.TypeOf(inputs["xIn"])) - return - } - for i, xIn := range xIns { - if vxIn[i] != xIn { - t.Errorf("ZKProver.GenerateInputs() xIn = %v, want %v", inputs["xIn"], xIns) + prvs := []prover.IZKProver{pjs, pgo} + + for i, p := range prvs { + t.Run(fmt.Sprintf("zk test %d", i), func(t *testing.T) { + inputsBytes, err := p.GenerateInputs(encodingKeys, sampleIdxs) + if err != nil { + t.Errorf("ZKProver.GenerateInputs() error = %v", err) return } - } - proof, publics, err := p.GenerateZKProofRaw(encodingKeys, sampleIdxs) - if err != nil { - t.Errorf("ZKProver.GenerateZKProof() error = %v ", err) - return - } - masks := publics[4:] - for i, encodingKey := range encodingKeys { - maskGo, err := GenerateMask(encodingKey, sampleIdxs[i]) + var inputs map[string]interface{} + err = json.Unmarshal(inputsBytes, &inputs) if err != nil { - t.Errorf("GenerateMask() error = %v", err) + t.Errorf("ZKProver.GenerateInputs() error = %v", err) + return + } + vxIn, ok := inputs["xIn"].([]interface{}) + if !ok { + t.Errorf("ZKProver.GenerateInputs() type: %v, want []interface{}", reflect.TypeOf(inputs["xIn"])) return } - if maskGo.Cmp(masks[i]) != 0 { - t.Errorf("ZKProver.GenerateZKProof() mask = %v, GeneratedMask %v", masks[i], maskGo) + for i, xIn := range xIns { + if vxIn[i] != xIn { + t.Errorf("ZKProver.GenerateInputs() xIn = %v, want %v", inputs["xIn"], xIns) + return + } + } + proof, publics, err := p.GenerateZKProofRaw(encodingKeys, sampleIdxs) + if err != nil { + t.Errorf("ZKProver.GenerateZKProof() error = %v ", err) return } - } - err = verifyProof(t, publics, proof) - if err != nil { - t.Errorf("ZKProver.GenerateZKProof() verifyProof err: %v", err) - return - } - t.Log("verifyProof success!") - }) + masks := publics[4:] + for i, encodingKey := range encodingKeys { + maskGo, err := GenerateMask(encodingKey, sampleIdxs[i]) + if err != nil { + t.Errorf("GenerateMask() error = %v", err) + return + } + if maskGo.Cmp(masks[i]) != 0 { + t.Errorf("ZKProver.GenerateZKProof() mask = %v, GeneratedMask %v", masks[i], maskGo) + return + } + } + err = verifyProof(t, publics, proof) + if err != nil { + t.Errorf("ZKProver.GenerateZKProof() verifyProof err: %v", err) + return + } + t.Log("verifyProof success!") + }) + } } // call Decoder2.sol diff --git a/integration_tests/zk_prover_test.go b/integration_tests/zk_prover_test.go index 182eaa86..8d16b748 100644 --- a/integration_tests/zk_prover_test.go +++ b/integration_tests/zk_prover_test.go @@ -51,85 +51,89 @@ func TestZKProver_GenerateZKProofPerSample(t *testing.T) { wantErr bool }{ { - "test chunk 0", + "test sample 0", args{encodingKey: common.HexToHash("0x1"), sampleIdx: 0}, "1", false, }, { - "test chunk 2222", + "test sample 2222", args{encodingKey: common.HexToHash("0x22222222222"), sampleIdx: 2222}, "13571350061658342048390665596699168162893949286891081722317471185110722978977", false, }, { - "test chunk 4095", + "test sample 4095", args{encodingKey: common.HexToHash("0x1e88fb83944b20562a100533d0521b90bf7df7cc6e0aaa1c46482b67c7b370ab"), sampleIdx: 4095}, "12199007973319674300030596965685270475268514105269206407619072166392043015767", false, }, } libDir := filepath.Join(proverPath, prover.SnarkLib) - p, err := prover.NewZKProver(libDir, zkeyName, prover.WasmName, lg) + pjs := prover.NewZKProver(proverPath, zkeyName, prover.WasmName, lg) + pgo, err := prover.NewZKProverGo(libDir, zkeyName, prover.WasmName, lg) if err != nil { t.Fatal(err) } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - inputBytes, err := p.GenerateInput(tt.args.encodingKey, tt.args.sampleIdx) - if err != nil { - t.Errorf("ZKProver.GenerateInput() error = %v", err) - return - } - var inputs map[string]interface{} - err = json.Unmarshal(inputBytes, &inputs) - if err != nil { - t.Errorf("ZKProver.GenerateInput() error = %v", err) - return - } - intputStr, ok := inputs["xIn"].(string) - if !ok { - t.Errorf("ZKProver.GenerateInput() type: %v, want string", reflect.TypeOf(inputs["xIn"])) - return - } - if intputStr != tt.xIn { - t.Errorf("ZKProver.GenerateInput() xIn = %v, want %v", inputs["xIn"], tt.xIn) - return - } - maskGo, err := GenerateMask(tt.args.encodingKey, tt.args.sampleIdx) - if (err != nil) != tt.wantErr { - t.Errorf("GenerateMask() error = %v, wantErr %v", err, tt.wantErr) - return - } - proofRaw, mask, err := p.GenerateZKProofPerSample(tt.args.encodingKey, tt.args.sampleIdx) - if (err != nil) != tt.wantErr { - t.Errorf("ZKProver.GenerateZKProofPerSample() error = %v, wantErr %v", err, tt.wantErr) - return - } - if maskGo.Cmp(mask) != 0 { - t.Errorf("ZKProver.GenerateZKProofPerSample() mask = %v, GenerateMask %v", mask, maskGo) - return - } - err = verifyDecodeSample(proofRaw, tt.args.sampleIdx, tt.args.encodingKey, mask) - if (err != nil) != tt.wantErr { - t.Errorf("ZKProver.GenerateZKProofPerSample() verifyDecodeSample err: %v", err) - return - } - t.Log("verifyDecodeSample success!") - }) + prvs := []prover.IZKProver{pjs, pgo} + for _, p := range prvs { + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + inputBytes, err := p.GenerateInput(tt.args.encodingKey, tt.args.sampleIdx) + if err != nil { + t.Errorf("ZKProver.GenerateInput() error = %v", err) + return + } + var inputs map[string]interface{} + err = json.Unmarshal(inputBytes, &inputs) + if err != nil { + t.Errorf("ZKProver.GenerateInput() error = %v", err) + return + } + intputStr, ok := inputs["xIn"].(string) + if !ok { + t.Errorf("ZKProver.GenerateInput() type: %v, want string", reflect.TypeOf(inputs["xIn"])) + return + } + if intputStr != tt.xIn { + t.Errorf("ZKProver.GenerateInput() xIn = %v, want %v", inputs["xIn"], tt.xIn) + return + } + maskGo, err := GenerateMask(tt.args.encodingKey, tt.args.sampleIdx) + if (err != nil) != tt.wantErr { + t.Errorf("GenerateMask() error = %v, wantErr %v", err, tt.wantErr) + return + } + proofRaw, mask, err := p.GenerateZKProofPerSample(tt.args.encodingKey, tt.args.sampleIdx) + if (err != nil) != tt.wantErr { + t.Errorf("ZKProver.GenerateZKProofPerSample() error = %v, wantErr %v", err, tt.wantErr) + return + } + if maskGo.Cmp(mask) != 0 { + t.Errorf("ZKProver.GenerateZKProofPerSample() mask = %v, GenerateMask %v", mask, maskGo) + return + } + err = verifyDecodeSample(proofRaw, tt.args.sampleIdx, tt.args.encodingKey, mask) + if (err != nil) != tt.wantErr { + t.Errorf("ZKProver.GenerateZKProofPerSample() verifyDecodeSample err: %v", err) + return + } + t.Log("verifyDecodeSample success!") + }) + } } } -func GenerateMask(encodingKey common.Hash, chunkIdx uint64) (*big.Int, error) { - if int(chunkIdx) >= eth.FieldElementsPerBlob { - return nil, fmt.Errorf("chunk index out of scope") +func GenerateMask(encodingKey common.Hash, sampleIdx uint64) (*big.Int, error) { + if int(sampleIdx) >= eth.FieldElementsPerBlob { + return nil, fmt.Errorf("sample index out of scope") } encodingKeyMod := fr.Modulus().Mod(encodingKey.Big(), fr.Modulus()) masks, err := encoder.Encode(common.BigToHash(encodingKeyMod), eth.FieldElementsPerBlob*32) if err != nil { return nil, err } - bytesIdx := chunkIdx * 32 + bytesIdx := sampleIdx * 32 mask := masks[bytesIdx : bytesIdx+32] return new(big.Int).SetBytes(mask), nil } From 3b087c17c5690d51cb057ce7ef96753fadb5d065 Mon Sep 17 00:00:00 2001 From: syntrust Date: Thu, 1 Feb 2024 11:14:43 +0800 Subject: [PATCH 20/45] refactor --- ethstorage/prover/zk_prover.go | 168 +++++++++------------------ integration_tests/kzg_prover_test.go | 14 +-- integration_tests/node_mine_test.go | 6 +- integration_tests/run_tests.sh | 6 +- 4 files changed, 69 insertions(+), 125 deletions(-) diff --git a/ethstorage/prover/zk_prover.go b/ethstorage/prover/zk_prover.go index 97c392bd..b3dc092f 100644 --- a/ethstorage/prover/zk_prover.go +++ b/ethstorage/prover/zk_prover.go @@ -10,7 +10,6 @@ import ( "os" "os/exec" "path/filepath" - "strings" "time" "github.com/consensys/gnark-crypto/ecc/bn254/fr" @@ -72,69 +71,14 @@ func (p *ZKProver) GenerateZKProofRaw(encodingKeys []common.Hash, sampleIdxs []u p.lg.Info("Generate zk proof done", "sampleIdx", sampleIdxs, "took(sec)", dur.Seconds()) }(start) - tempDir := crypto.Keccak256Hash([]byte(fmt.Sprint(encodingKeys, sampleIdxs))) - p.lg.Debug("Generate zk proof", "path", common.Bytes2Hex(tempDir[:])) - buildDir := filepath.Join(p.dir, snarkBuildDir, common.Bytes2Hex(tempDir[:])) - if _, err := os.Stat(buildDir); err == nil { - os.RemoveAll(buildDir) - } - err := os.Mkdir(buildDir, os.ModePerm) - if err != nil { - p.lg.Error("Generate zk proof failed", "mkdir", buildDir, "error", err) - return nil, nil, err - } - libDir := filepath.Join(p.dir, SnarkLib) - - // 1. Generate input - inputs, err := p.GenerateInputs(encodingKeys, sampleIdxs) + pubInputs, err := p.GenerateInputs(encodingKeys, sampleIdxs) if err != nil { p.lg.Error("Generate inputs failed", "error", err) return nil, nil, err } - inputFile := filepath.Join(buildDir, inputName) - err = os.WriteFile(inputFile, inputs, 0644) - if err != nil { - fmt.Println("Unable to write file:", err) - return nil, nil, err - } - - // 2. Generate witness - wtnsFile := filepath.Join(buildDir, witnessName) - cmd := exec.Command("node", - filepath.Join(libDir, witnessGenerator), - filepath.Join(libDir, p.wasmName), - inputFile, - wtnsFile, - ) - cmd.Dir = libDir - out, err := cmd.Output() + proof, publicFile, err := p.prove(fmt.Sprint(encodingKeys, sampleIdxs), pubInputs) if err != nil { - p.lg.Error("Generate witness failed", "error", err, "cmd", cmd.String(), "output", string(out)) - return nil, nil, err - } - p.lg.Debug("Generate witness done") - - // 3. Generate proof - proofFile := filepath.Join(buildDir, proofName) - publicFile := filepath.Join(buildDir, publicName) - cmd = exec.Command("snarkjs", "groth16", "prove", - filepath.Join(libDir, p.zkeyName), - wtnsFile, - proofFile, - publicFile, - ) - cmd.Dir = libDir - out, err = cmd.Output() - if err != nil { - p.lg.Error("Generate proof failed", "error", err, "cmd", cmd.String(), "output", string(out)) - return nil, nil, err - } - p.lg.Debug("Generate proof done") - - // 4. Read proof and masks - proof, err := readProofFrom(proofFile) - if err != nil { - p.lg.Error("Parse proof failed", "error", err) + p.lg.Error("Generate proof failed", "error", err) return nil, nil, err } publics, err := readPublicsFrom(publicFile) @@ -142,6 +86,7 @@ func (p *ZKProver) GenerateZKProofRaw(encodingKeys []common.Hash, sampleIdxs []u p.lg.Error("Read publics failed", "error", err) return nil, nil, err } + os.RemoveAll(filepath.Dir(publicFile)) return proof, publics, nil } @@ -170,7 +115,6 @@ func (p *ZKProver) GenerateInputs(encodingKeys []common.Hash, sampleIdxs []uint6 return inputs, nil } -// Generate ZK Proof for the given encoding key and chunck index using snarkjs func (p *ZKProver) GenerateZKProofPerSample(encodingKey common.Hash, sampleIdx uint64) ([]byte, *big.Int, error) { p.lg.Debug("Generate zk proof", "encodingKey", encodingKey.Hex(), "sampleIdx", sampleIdx) if int(sampleIdx) >= eth.FieldElementsPerBlob { @@ -179,36 +123,69 @@ func (p *ZKProver) GenerateZKProofPerSample(encodingKey common.Hash, sampleIdx u start := time.Now() defer func(start time.Time) { dur := time.Since(start) - p.lg.Info("Generate zk proof", "sampleIdx", sampleIdx, "took(sec)", dur.Seconds()) + p.lg.Info("Generate zk proof done", "sampleIdx", sampleIdx, "took(sec)", dur.Seconds()) }(start) - buildDir := filepath.Join(p.dir, snarkBuildDir, strings.Join([]string{ - encodingKey.Hex(), - fmt.Sprint(sampleIdx), - }, "-")) + + pubInput, err := p.GenerateInput(encodingKey, sampleIdx) + if err != nil { + p.lg.Error("Generate input failed", "error", err) + return nil, nil, err + } + + proof, publicFile, err := p.prove(fmt.Sprint(encodingKey, sampleIdx), pubInput) + if err != nil { + p.lg.Error("Generate proof failed", "error", err) + return nil, nil, err + } + mask, err := readMaskFrom(publicFile) + if err != nil { + p.lg.Error("Read mask failed", "error", err) + return nil, nil, err + } + os.RemoveAll(filepath.Dir(publicFile)) + return proof, mask, nil +} + +func (p *ZKProver) GenerateInput(encodingKey common.Hash, sampleIdx uint64) ([]byte, error) { + var b fr.Element + var exp big.Int + exp.Div(exp.Sub(fr.Modulus(), common.Big1), big.NewInt(int64(eth.FieldElementsPerBlob))) + ru := b.Exp(*b.SetInt64(5), &exp) + xIn := ru.Exp(*ru, big.NewInt(int64(sampleIdx))) + encodingKeyMod := fr.Modulus().Mod(encodingKey.Big(), fr.Modulus()) + inputObj := InputPair{ + EncodingKeyIn: hexutil.Encode(encodingKeyMod.Bytes()), + XIn: xIn.String(), + } + input, err := json.Marshal(inputObj) + if err != nil { + p.lg.Error("Encode input failed", "error", err) + return nil, err + } + p.lg.Debug("Generate zk proof", "input", inputObj) + return input, nil +} + +func (p *ZKProver) prove(dir string, pubInputs []byte) ([]byte, string, error) { + temp := crypto.Keccak256Hash([]byte(dir)) + buildDir := filepath.Join(p.dir, snarkBuildDir, common.Bytes2Hex(temp[:])) + p.lg.Debug("Generate zk proof", "path", buildDir) if _, err := os.Stat(buildDir); err == nil { os.RemoveAll(buildDir) } err := os.Mkdir(buildDir, os.ModePerm) if err != nil { p.lg.Error("Generate zk proof failed", "mkdir", buildDir, "error", err) - return nil, nil, err + return nil, "", err } - libDir := filepath.Join(p.dir, SnarkLib) - // 1. Generate input - input, err := p.GenerateInput(encodingKey, sampleIdx) - if err != nil { - p.lg.Error("Generate input failed", "error", err) - return nil, nil, err - } inputFile := filepath.Join(buildDir, inputName) - err = os.WriteFile(inputFile, input, 0644) + err = os.WriteFile(inputFile, pubInputs, 0644) if err != nil { fmt.Println("Unable to write file:", err) - return nil, nil, err + return nil, "", err } - - // 2. Generate witness + libDir := filepath.Join(p.dir, SnarkLib) wtnsFile := filepath.Join(buildDir, witnessName) cmd := exec.Command("node", filepath.Join(libDir, witnessGenerator), @@ -220,11 +197,9 @@ func (p *ZKProver) GenerateZKProofPerSample(encodingKey common.Hash, sampleIdx u out, err := cmd.Output() if err != nil { p.lg.Error("Generate witness failed", "error", err, "cmd", cmd.String(), "output", string(out)) - return nil, nil, err + return nil, "", err } p.lg.Debug("Generate witness done") - - // 3. Generate proof proofFile := filepath.Join(buildDir, proofName) publicFile := filepath.Join(buildDir, publicName) cmd = exec.Command("snarkjs", "groth16", "prove", @@ -237,40 +212,13 @@ func (p *ZKProver) GenerateZKProofPerSample(encodingKey common.Hash, sampleIdx u out, err = cmd.Output() if err != nil { p.lg.Error("Generate proof failed", "error", err, "cmd", cmd.String(), "output", string(out)) - return nil, nil, err + return nil, "", err } p.lg.Debug("Generate proof done") - - // 4. Read proof and mask proof, err := readProofFrom(proofFile) if err != nil { p.lg.Error("Parse proof failed", "error", err) - return nil, nil, err - } - mask, err := readMaskFrom(publicFile) - if err != nil { - p.lg.Error("Read mask failed", "error", err) - return nil, nil, err + return nil, "", err } - return proof, mask, nil -} - -func (p *ZKProver) GenerateInput(encodingKey common.Hash, sampleIdx uint64) ([]byte, error) { - var b fr.Element - var exp big.Int - exp.Div(exp.Sub(fr.Modulus(), common.Big1), big.NewInt(int64(eth.FieldElementsPerBlob))) - ru := b.Exp(*b.SetInt64(5), &exp) - xIn := ru.Exp(*ru, big.NewInt(int64(sampleIdx))) - encodingKeyMod := fr.Modulus().Mod(encodingKey.Big(), fr.Modulus()) - inputObj := InputPair{ - EncodingKeyIn: hexutil.Encode(encodingKeyMod.Bytes()), - XIn: xIn.String(), - } - input, err := json.Marshal(inputObj) - if err != nil { - p.lg.Error("Encode input failed", "error", err) - return nil, err - } - p.lg.Debug("Generate zk proof", "input", inputObj) - return input, nil + return proof, publicFile, err } diff --git a/integration_tests/kzg_prover_test.go b/integration_tests/kzg_prover_test.go index 353c5fa6..e0e8f0d7 100644 --- a/integration_tests/kzg_prover_test.go +++ b/integration_tests/kzg_prover_test.go @@ -28,13 +28,13 @@ var kzgContract = common.HexToAddress(os.Getenv("ES_NODE_STORAGE_L1CONTRACT_KZG" func TestKZGProver_GenerateKZGProof(t *testing.T) { lg.Info("KZG prover test", "contract", kzgContract) - dataRaw := generateRandomContent(128) + dataRaw := generateRandomContent(124) dataHash := uploadBlob(t, dataRaw) blobs := utils.EncodeBlobs(dataRaw) blob := blobs[0][:] tests := []struct { - name string - chunkIdx uint64 + name string + sampleIdx uint64 }{ {"check 0 th element", 0, @@ -49,7 +49,7 @@ func TestKZGProver_GenerateKZGProof(t *testing.T) { p := prover.NewKZGProver(lg) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - peInput, err := p.GenerateKZGProof(blob, tt.chunkIdx) + peInput, err := p.GenerateKZGProof(blob, tt.sampleIdx) if err != nil { t.Errorf("KZGProver.GenerateKZGProof() error = %v", err) return @@ -58,7 +58,7 @@ func TestKZGProver_GenerateKZGProof(t *testing.T) { t.Errorf("dataHash not correct: off-chain %v, on-chain %v", peInput[0:24], dataHash[:24]) return } - err = verifyInclusive(tt.chunkIdx, peInput) + err = verifyInclusive(tt.sampleIdx, peInput) if err != nil { t.Errorf("verifyInclusive() error = %v", err) return @@ -137,10 +137,10 @@ func uploadBlob(t *testing.T, data []byte) common.Hash { true, int64(n), storageCost.String(), - 510000, + 150000, "", "", - "100000000", + "40000000000", chainID.String(), "0x"+common.Bytes2Hex(calldata), ) diff --git a/integration_tests/node_mine_test.go b/integration_tests/node_mine_test.go index 91ce1e5a..4fd3f114 100644 --- a/integration_tests/node_mine_test.go +++ b/integration_tests/node_mine_test.go @@ -249,7 +249,7 @@ func fillEmpty(t *testing.T, l1Client *eth.PollingClient, storageMgr *ethstorage } func prepareData(t *testing.T, l1Client *eth.PollingClient, storageMgr *ethstorage.StorageManager, value string) { - data := generateRandomContent(128 * 10) + data := generateRandomContent(124 * 10) blobs := utils.EncodeBlobs(data) t.Logf("Blobs len %d \n", len(blobs)) var hashs []common.Hash @@ -413,10 +413,6 @@ func initMiningConfig(t *testing.T, l1Contract common.Address, client *eth.Polli miningConfig.ZKeyFileName = zkey2Name proverPath, _ := filepath.Abs(prPath) - zkeyFull := filepath.Join(proverPath, prover.SnarkLib, miningConfig.ZKeyFileName) - if _, err := os.Stat(zkeyFull); os.IsNotExist(err) { - t.Fatalf("%s not found", zkeyFull) - } miningConfig.ZKWorkingDir = proverPath miningConfig.ZKProverMode = 2 miningConfig.ZKProverImp = 1 diff --git a/integration_tests/run_tests.sh b/integration_tests/run_tests.sh index 3d199c64..fb6bc2b0 100755 --- a/integration_tests/run_tests.sh +++ b/integration_tests/run_tests.sh @@ -18,15 +18,15 @@ if [ -z "$ES_NODE_STORAGE_MINER" ]; then fi # A contract that will be update with new blob uploaded for the KZG test if [ -z "$ES_NODE_STORAGE_L1CONTRACT_KZG" ]; then - export ES_NODE_STORAGE_L1CONTRACT_KZG=0x1Cf97d51d305e1e84132Ee504F6B20F5162355fD + export ES_NODE_STORAGE_L1CONTRACT_KZG=0xB6e01Ca0c33B2bAbd2eccf008F0759131FC284dB fi # A contract address that clef server checks against before signing the miner transaction if [ -z "$ES_NODE_STORAGE_L1CONTRACT_CLEF" ]; then - export ES_NODE_STORAGE_L1CONTRACT_CLEF=0x1Cf97d51d305e1e84132Ee504F6B20F5162355fD + export ES_NODE_STORAGE_L1CONTRACT_CLEF=0xB6e01Ca0c33B2bAbd2eccf008F0759131FC284dB fi # A newly deployed contract is required for each run for miner test, with zkp verifier of mode 2 if [ -z "$ES_NODE_STORAGE_L1CONTRACT" ]; then - export ES_NODE_STORAGE_L1CONTRACT=0x1Cf97d51d305e1e84132Ee504F6B20F5162355fD + export ES_NODE_STORAGE_L1CONTRACT=0xB6e01Ca0c33B2bAbd2eccf008F0759131FC284dB fi # A contract with zkp verifier of mode 1 (one proof per sample) if [ -z "$ES_NODE_STORAGE_L1CONTRACT_ZKP1" ]; then From 4d9507678538921a13d3045b4a05177f4cb29673 Mon Sep 17 00:00:00 2001 From: syntrust Date: Thu, 1 Feb 2024 12:01:22 +0800 Subject: [PATCH 21/45] refactor --- ethstorage/miner/cli.go | 16 +-- ethstorage/miner/config.go | 4 +- ethstorage/miner/miner_test.go | 4 +- ethstorage/node/node.go | 2 +- ethstorage/prover/kzg_poseidon_prover.go | 39 +++--- .../blob_poseidon2_verification_key.json | 119 ------------------ .../blob_poseidon_verification_key.json | 104 --------------- integration_tests/node_mine_test.go | 4 +- 8 files changed, 32 insertions(+), 260 deletions(-) delete mode 100644 ethstorage/prover/snark_lib/blob_poseidon2_verification_key.json delete mode 100644 ethstorage/prover/snark_lib/blob_poseidon_verification_key.json diff --git a/ethstorage/miner/cli.go b/ethstorage/miner/cli.go index 2e28f2c3..29868889 100644 --- a/ethstorage/miner/cli.go +++ b/ethstorage/miner/cli.go @@ -22,7 +22,7 @@ const ( ZKeyFileNameFlagName = "miner.zkey" ZKWorkingDirFlagName = "miner.zk-working-dir" ZKProverModeFlagName = "miner.zk-prover-mode" - ZKProverImpFlagName = "miner.zk-prover-imp" + ZKProverImplFlagName = "miner.zk-prover-impl" ThreadsPerShardFlagName = "miner.threads-per-shard" MinimumProfitFlagName = "miner.min-profit" ) @@ -69,13 +69,13 @@ func CLIFlags(envPrefix string) []cli.Flag { Name: ZKProverModeFlagName, Usage: "ZK prover mode, 1: one proof per sample, 2: one proof for multiple samples", Value: DefaultConfig.ZKProverMode, - EnvVar: rollup.PrefixEnvVar(envPrefix, "ZK_PROVER_Mode"), + EnvVar: rollup.PrefixEnvVar(envPrefix, "ZK_PROVER_MODE"), }, cli.Uint64Flag{ - Name: ZKProverImpFlagName, + Name: ZKProverImplFlagName, Usage: "ZK prover implementation, 1: snarkjs, 2: go-rapidsnark", - Value: DefaultConfig.ZKProverImp, - EnvVar: rollup.PrefixEnvVar(envPrefix, "ZK_PROVER_IMP"), + Value: DefaultConfig.ZKProverImpl, + EnvVar: rollup.PrefixEnvVar(envPrefix, "ZK_PROVER_IMPL"), }, cli.Uint64Flag{ Name: ThreadsPerShardFlagName, @@ -95,7 +95,7 @@ type CLIConfig struct { ZKeyFileName string ZKWorkingDir string ZKProverMode uint64 - ZKProverImp uint64 + ZKProverImpl uint64 ThreadsPerShard uint64 } @@ -125,7 +125,7 @@ func (c CLIConfig) ToMinerConfig() (Config, error) { cfg.MinimumProfit = c.MinimumProfit cfg.ZKeyFileName = c.ZKeyFileName cfg.ZKProverMode = c.ZKProverMode - cfg.ZKProverImp = c.ZKProverImp + cfg.ZKProverImpl = c.ZKProverImpl cfg.ThreadsPerShard = c.ThreadsPerShard return cfg, nil } @@ -139,7 +139,7 @@ func ReadCLIConfig(ctx *cli.Context) CLIConfig { ZKeyFileName: ctx.GlobalString(ZKeyFileNameFlagName), ZKWorkingDir: ctx.GlobalString(ZKWorkingDirFlagName), ZKProverMode: ctx.GlobalUint64(ZKProverModeFlagName), - ZKProverImp: ctx.GlobalUint64(ZKProverImpFlagName), + ZKProverImpl: ctx.GlobalUint64(ZKProverImplFlagName), ThreadsPerShard: ctx.GlobalUint64(ThreadsPerShardFlagName), } return cfg diff --git a/ethstorage/miner/config.go b/ethstorage/miner/config.go index 1d7799fd..f159c66c 100644 --- a/ethstorage/miner/config.go +++ b/ethstorage/miner/config.go @@ -32,7 +32,7 @@ type Config struct { ZKeyFileName string ZKWorkingDir string ZKProverMode uint64 - ZKProverImp uint64 + ZKProverImpl uint64 ThreadsPerShard uint64 SignerFnFactory signer.SignerFactory SignerAddr common.Address @@ -51,7 +51,7 @@ var DefaultConfig = Config{ ZKeyFileName: "blob_poseidon2.zkey", ZKWorkingDir: filepath.Join("build", "bin"), ZKProverMode: 2, - ZKProverImp: 1, + ZKProverImpl: 1, ThreadsPerShard: uint64(2 * runtime.NumCPU()), MinimumProfit: common.Big0, } diff --git a/ethstorage/miner/miner_test.go b/ethstorage/miner/miner_test.go index 75be12b7..ef06fb1f 100644 --- a/ethstorage/miner/miner_test.go +++ b/ethstorage/miner/miner_test.go @@ -61,12 +61,12 @@ func newMiner(t *testing.T, storageMgr *es.StorageManager, client *eth.PollingCl PriorityGasPrice: new(big.Int).SetUint64(10), ThreadsPerShard: 1, ZKProverMode: 2, - ZKProverImp: 1, + ZKProverImpl: 1, ZKeyFileName: "blob_poseidon2.zkey", } l1api := NewL1MiningAPI(client, lg) zkWorkingDir, _ := filepath.Abs("../prover") - pvr := prover.NewKZGPoseidonProver(zkWorkingDir, defaultConfig.ZKeyFileName, defaultConfig.ZKProverMode, defaultConfig.ZKProverImp, lg) + pvr := prover.NewKZGPoseidonProver(zkWorkingDir, defaultConfig.ZKeyFileName, defaultConfig.ZKProverMode, defaultConfig.ZKProverImpl, lg) fd := new(event.Feed) miner := New(defaultConfig, storageMgr, l1api, &pvr, fd, lg) return miner diff --git a/ethstorage/node/node.go b/ethstorage/node/node.go index 37b7a473..e7888d58 100644 --- a/ethstorage/node/node.go +++ b/ethstorage/node/node.go @@ -252,7 +252,7 @@ func (n *EsNode) initMiner(ctx context.Context, cfg *Config) error { cfg.Mining.ZKWorkingDir, cfg.Mining.ZKeyFileName, cfg.Mining.ZKProverMode, - cfg.Mining.ZKProverImp, + cfg.Mining.ZKProverImpl, n.log, ) n.miner = miner.New(cfg.Mining, n.storageManager, l1api, &pvr, n.feed, n.log) diff --git a/ethstorage/prover/kzg_poseidon_prover.go b/ethstorage/prover/kzg_poseidon_prover.go index ba333ead..8b4685e9 100644 --- a/ethstorage/prover/kzg_poseidon_prover.go +++ b/ethstorage/prover/kzg_poseidon_prover.go @@ -35,9 +35,10 @@ const ( type KZGPoseidonProver struct { zkProverMode uint64 - zkProverImp uint64 + zkProverImpl uint64 libDir string zkey string + wasm string lg log.Logger } @@ -45,15 +46,15 @@ type KZGPoseidonProver struct { // workingDir specifies the working directory of the command relative to the caller. // zkeyFileName specifies the zkey file name to generate snark proof // zkProverMode specifies the mode of the zk prover, 1 for per sample, 2 for samples -// zkProverImp specifies the implementation of the zk prover, 1 for snarkjs, 2 for go-rapidsnark +// zkProverImpl specifies the implementation of the snark prover, 1 for snarkjs, 2 for go-rapidsnark // lg specifies the logger to log the info // returns a prover that can generate a combined KZG + zk proof -func NewKZGPoseidonProverWithLogger(workingDir, zkeyFileName string, zkProverMode, zkProverImp uint64, lg log.Logger) KZGPoseidonProver { - return NewKZGPoseidonProver(workingDir, zkeyFileName, zkProverMode, zkProverImp, lg) +func NewKZGPoseidonProverWithLogger(workingDir, zkeyFileName string, zkProverMode, zkProverImpl uint64, lg log.Logger) KZGPoseidonProver { + return NewKZGPoseidonProver(workingDir, zkeyFileName, zkProverMode, zkProverImpl, lg) } // returns a prover that can generate a combined KZG + zk proof -func NewKZGPoseidonProver(workingDir, zkeyFileName string, zkProverMode, zkProverImp uint64, lg log.Logger) KZGPoseidonProver { +func NewKZGPoseidonProver(workingDir, zkeyFileName string, zkProverMode, zkProverImpl uint64, lg log.Logger) KZGPoseidonProver { // check dependencies when es-node starts libDir := filepath.Join(workingDir, SnarkLib) if _, err := os.Stat(libDir); errors.Is(err, os.ErrNotExist) { @@ -63,22 +64,24 @@ func NewKZGPoseidonProver(workingDir, zkeyFileName string, zkProverMode, zkProve if _, err := os.Stat(zkeyFile); errors.Is(err, os.ErrNotExist) { lg.Crit("Init ZK prover failed", "error", "zkey does not exist", "dir", zkeyFile) } - var wasmFile string + var wasmName string if zkProverMode == 2 { - wasmFile = filepath.Join(libDir, Wasm2Name) + wasmName = Wasm2Name } else if zkProverMode == 1 { - wasmFile = filepath.Join(libDir, WasmName) + wasmName = WasmName } else { lg.Crit("Init ZK prover failed", "error", "invalid zkProverMode", "mode", zkProverMode) } + wasmFile := filepath.Join(libDir, wasmName) if _, err := os.Stat(wasmFile); errors.Is(err, os.ErrNotExist) { lg.Crit("Init ZK prover failed", "error", "wasm does not exist", "dir", wasmFile) } return KZGPoseidonProver{ zkProverMode: zkProverMode, - zkProverImp: zkProverImp, + zkProverImpl: zkProverImpl, libDir: libDir, zkey: zkeyFileName, + wasm: wasmName, lg: lg, } } @@ -128,19 +131,11 @@ func (p *KZGPoseidonProver) GetStorageProof(data [][]byte, encodingKeys []common } func (p *KZGPoseidonProver) getZKProver() (IZKProver, error) { - var wasm string - if p.zkProverMode == 2 { - wasm = WasmName - } else if p.zkProverMode == 1 { - wasm = WasmName - } else { - return nil, fmt.Errorf("invalid zk proof mode") - } - if p.zkProverImp == 1 { - return NewZKProver(filepath.Dir(p.libDir), p.zkey, wasm, p.lg), nil + if p.zkProverImpl == 1 { + return NewZKProver(filepath.Dir(p.libDir), p.zkey, p.wasm, p.lg), nil } - if p.zkProverImp == 2 { - return NewZKProverGo(p.libDir, p.zkey, wasm, p.lg) + if p.zkProverImpl == 2 { + return NewZKProverGo(p.libDir, p.zkey, p.wasm, p.lg) } - return nil, fmt.Errorf("invalid zk prover implementation: %d", p.zkProverImp) + return nil, fmt.Errorf("invalid zk prover implementation: %d", p.zkProverImpl) } diff --git a/ethstorage/prover/snark_lib/blob_poseidon2_verification_key.json b/ethstorage/prover/snark_lib/blob_poseidon2_verification_key.json deleted file mode 100644 index 93c5bfac..00000000 --- a/ethstorage/prover/snark_lib/blob_poseidon2_verification_key.json +++ /dev/null @@ -1,119 +0,0 @@ -{ - "protocol": "groth16", - "curve": "bn128", - "nPublic": 6, - "vk_alpha_1": [ - "7506542393861712633345351046961518695186434969159573929710445813801252250723", - "16226065335411284296170178517395602646321797300570911178122732619405801531786", - "1" - ], - "vk_beta_2": [ - [ - "14634453066859375398229234242235662432488733031061395747558146261931733463655", - "18085759018360810108311053436144684567975240874798592024271494525670832624248" - ], - [ - "15883666510464263642223723115318135885418478949233288914773546058946554436604", - "5381338245488965956306749233704530527583477992038243832593582681279872987470" - ], - [ - "1", - "0" - ] - ], - "vk_gamma_2": [ - [ - "10857046999023057135944570762232829481370756359578518086990519993285655852781", - "11559732032986387107991004021392285783925812861821192530917403151452391805634" - ], - [ - "8495653923123431417604973247489272438418190587263600148770280649306958101930", - "4082367875863433681332203403145435568316851327593401208105741076214120093531" - ], - [ - "1", - "0" - ] - ], - "vk_delta_2": [ - [ - "10890565504224301114874433160320698556606628868096993643809081156365267213249", - "12835677679493139045269931295051448329793403398705026697877485711464362140790" - ], - [ - "20093054666161765761327580477678108845241889769892444974271179780900242692838", - "4820425325906337717692330783154620996810762479415825588979740850757518563223" - ], - [ - "1", - "0" - ] - ], - "vk_alphabeta_12": [ - [ - [ - "3637437409031110153941205210051322020546157607853100397804089258525902699154", - "7725601260258828088705131396694191819805390450228506886453367245979964628165" - ], - [ - "18154498297774931471780232905904902084379102465867003940101600010498138601393", - "6220396953860122558794898380190113886588885092775776180339824831923246869002" - ], - [ - "14908577140753234934937396524483383243317127572120492623404140127739496612680", - "2857902896464898498429962557275956854053218591378088994600064230193331420175" - ] - ], - [ - [ - "6079031818388448413378318289497602060285167318160755219791580021548962060196", - "2271882866267465182952948218478901964920590607353592242605475224359293411357" - ], - [ - "308461206053147204966781104468271248410725368530630213173294988207497229548", - "15101308468467910128204676842491426591456837911268249640130581307391620927150" - ], - [ - "7382938091799076068307869524881409900699716463362612740053868015306985867866", - "6769025393531002524384611155740654941260367334178791754934017435282926288429" - ] - ] - ], - "IC": [ - [ - "21859776616790133348839467181671732914251000215306575824317360595804907051375", - "5948124107564618515449715251945373028277412284372620284583980914047280102876", - "1" - ], - [ - "7520522526360393336256191862722677948012949593965997902878602990224219591269", - "18122129100184838347758272212675964028707019394412040910218297874776889131339", - "1" - ], - [ - "9999628984230624978359278370848255996127491687253422284834743304166137276639", - "1555065374953614187921236262540138367937263242920725070578958971136763113533", - "1" - ], - [ - "10835355946958950355842429995606773830353386704839836610977135010867467767886", - "347681805283999531579989309847502060079457705975188603961036829994986965556", - "1" - ], - [ - "18753041537644146645964636680858664682282695577221297145676895383600075612749", - "4206563387370580535351146610430324298862523672147419676700216935123282436586", - "1" - ], - [ - "4442990650008179863485607955771945665024984641422192665573627724614025985085", - "12258170331083523204110753037449846946259145197015177866805657404915928554507", - "1" - ], - [ - "9756223775418760164233100362456726133526680277789326181795061439535609246955", - "14662783377248180262259778967741304849392652193971992154747894564718718444840", - "1" - ] - ] -} \ No newline at end of file diff --git a/ethstorage/prover/snark_lib/blob_poseidon_verification_key.json b/ethstorage/prover/snark_lib/blob_poseidon_verification_key.json deleted file mode 100644 index 62a89f75..00000000 --- a/ethstorage/prover/snark_lib/blob_poseidon_verification_key.json +++ /dev/null @@ -1,104 +0,0 @@ -{ - "protocol": "groth16", - "curve": "bn128", - "nPublic": 3, - "vk_alpha_1": [ - "7506542393861712633345351046961518695186434969159573929710445813801252250723", - "16226065335411284296170178517395602646321797300570911178122732619405801531786", - "1" - ], - "vk_beta_2": [ - [ - "14634453066859375398229234242235662432488733031061395747558146261931733463655", - "18085759018360810108311053436144684567975240874798592024271494525670832624248" - ], - [ - "15883666510464263642223723115318135885418478949233288914773546058946554436604", - "5381338245488965956306749233704530527583477992038243832593582681279872987470" - ], - [ - "1", - "0" - ] - ], - "vk_gamma_2": [ - [ - "10857046999023057135944570762232829481370756359578518086990519993285655852781", - "11559732032986387107991004021392285783925812861821192530917403151452391805634" - ], - [ - "8495653923123431417604973247489272438418190587263600148770280649306958101930", - "4082367875863433681332203403145435568316851327593401208105741076214120093531" - ], - [ - "1", - "0" - ] - ], - "vk_delta_2": [ - [ - "10890565504224301114874433160320698556606628868096993643809081156365267213249", - "12835677679493139045269931295051448329793403398705026697877485711464362140790" - ], - [ - "20093054666161765761327580477678108845241889769892444974271179780900242692838", - "4820425325906337717692330783154620996810762479415825588979740850757518563223" - ], - [ - "1", - "0" - ] - ], - "vk_alphabeta_12": [ - [ - [ - "3637437409031110153941205210051322020546157607853100397804089258525902699154", - "7725601260258828088705131396694191819805390450228506886453367245979964628165" - ], - [ - "18154498297774931471780232905904902084379102465867003940101600010498138601393", - "6220396953860122558794898380190113886588885092775776180339824831923246869002" - ], - [ - "14908577140753234934937396524483383243317127572120492623404140127739496612680", - "2857902896464898498429962557275956854053218591378088994600064230193331420175" - ] - ], - [ - [ - "6079031818388448413378318289497602060285167318160755219791580021548962060196", - "2271882866267465182952948218478901964920590607353592242605475224359293411357" - ], - [ - "308461206053147204966781104468271248410725368530630213173294988207497229548", - "15101308468467910128204676842491426591456837911268249640130581307391620927150" - ], - [ - "7382938091799076068307869524881409900699716463362612740053868015306985867866", - "6769025393531002524384611155740654941260367334178791754934017435282926288429" - ] - ] - ], - "IC": [ - [ - "15916933300299841326133363619464745675297622793331552584323366408211376395967", - "2204695882423366014128738034688798906136516188846113906761598291124965575312", - "1" - ], - [ - "4622856607165460859549457180034620471823207414430476098696107310517129298612", - "8316856443679694570367215915233834858969193163656242228258052534650350302793", - "1" - ], - [ - "5915523109966219878936187973377718245049119188043618969861196210655718832719", - "19707299613116331139635042453248814599694182156604393507335721697711099774908", - "1" - ], - [ - "11851222670115883100836444147396391086571308795728318034006095130793195411204", - "21124748331098730840633663986704312647589675061705229552977471659873651158043", - "1" - ] - ] -} \ No newline at end of file diff --git a/integration_tests/node_mine_test.go b/integration_tests/node_mine_test.go index 4fd3f114..679e1419 100644 --- a/integration_tests/node_mine_test.go +++ b/integration_tests/node_mine_test.go @@ -78,7 +78,7 @@ func TestMining(t *testing.T) { miningConfig.ZKWorkingDir, miningConfig.ZKeyFileName, miningConfig.ZKProverMode, - miningConfig.ZKProverImp, + miningConfig.ZKProverImpl, lg, ) mnr := miner.New(miningConfig, storageManager, l1api, &pvr, feed, lg) @@ -415,7 +415,7 @@ func initMiningConfig(t *testing.T, l1Contract common.Address, client *eth.Polli proverPath, _ := filepath.Abs(prPath) miningConfig.ZKWorkingDir = proverPath miningConfig.ZKProverMode = 2 - miningConfig.ZKProverImp = 1 + miningConfig.ZKProverImpl = 1 miningConfig.ThreadsPerShard = 2 miningConfig.MinimumProfit = new(big.Int).SetInt64(-1e18) return miningConfig From c0658b8fe17a2ed87b89c3397ee4139f674688be Mon Sep 17 00:00:00 2001 From: syntrust Date: Thu, 1 Feb 2024 12:37:53 +0800 Subject: [PATCH 22/45] pass flag --- .github/workflows/publish.yml | 3 ++- README.md | 3 ++- docker-compose.yaml | 2 +- integration_tests/node_mine_test.go | 3 +-- run.sh | 34 ++++++++++++++++++++++++++++- 5 files changed, 39 insertions(+), 6 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index e644a29d..a5b568b2 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -24,7 +24,8 @@ jobs: - name: Create package run: | - cp -r ethstorage/prover/snark_lib ${{ env.BIN_DIR }} + mkdir -p ${{ env.BIN_DIR }}/snarkbuild + cp -r ethstorage/prover/snarkjs ${{ env.BIN_DIR }} cp run.sh ${{ env.BUILD_DIR }} - name: Build diff --git a/README.md b/README.md index 9d64c5fd..6c14ebaa 100644 --- a/README.md +++ b/README.md @@ -84,8 +84,9 @@ The full list of options that you can use to configure an es-node are as follows |`--miner.priority-gas-price`|Priority gas price for mining transactions||| |`--miner.threads-per-shard`|Number of threads per shard|`runtime.NumCPU() x 2`|| |`--miner.zk-prover-version value`|ZK prover version, 1: one proof per sample, 2: one proof for multiple samples|`2`|| -|`--miner.zk-working-dir`|Path to the snark_lib folder|`build/bin`|| |`--miner.zk-prover-mode`|ZK prover mode, 1: one proof per sample, 2: one proof for multiple samples|`2`|| +|`--miner.zk-prover-impl`|ZK prover implmentation, 1: snarkjs, 2: go-rapidsnark|`1`|| +|`--miner.zk-working-dir`|Path to the snark_lib folder|`build/bin`|| |`--miner.zkey`|zkey file name which should be put in the snark_lib folder|`blob_poseidon2.zkey`|| |`--network`|Predefined L1 network selection. Available networks: devnet||| |`--p2p.advertise.ip`|The IP address to advertise in Discv5, put into the ENR of the node. This may also be a hostname / domain name to resolve to an IP.||| diff --git a/docker-compose.yaml b/docker-compose.yaml index 737428e7..c0a42245 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -11,6 +11,6 @@ services: environment: - ES_NODE_STORAGE_MINER=${ES_NODE_STORAGE_MINER} - ES_NODE_SIGNER_PRIVATE_KEY=${ES_NODE_SIGNER_PRIVATE_KEY} - command: /es-node/run.sh + command: ["sh", "-c", "/es-node/run.sh --miner.zk-prover-impl=2"] container_name: es tty: true diff --git a/integration_tests/node_mine_test.go b/integration_tests/node_mine_test.go index 679e1419..6476e57b 100644 --- a/integration_tests/node_mine_test.go +++ b/integration_tests/node_mine_test.go @@ -8,7 +8,6 @@ package integration import ( "context" "fmt" - "io/ioutil" "math/big" "os" "path/filepath" @@ -158,7 +157,7 @@ func cleanFiles(proverDir string) { } folderPath := filepath.Join(proverDir, "snarkbuild") - files, err := ioutil.ReadDir(folderPath) + files, err := os.ReadDir(folderPath) if err != nil { fmt.Println(err) return diff --git a/run.sh b/run.sh index b7856b39..0b8f8ecc 100755 --- a/run.sh +++ b/run.sh @@ -43,7 +43,7 @@ while [ $i -le $# ]; do done if [ "$zkp_mode" != 1 ] && [ "$zkp_mode" != 2 ]; then - echo "zk prover mode can only be 1 or 2" + echo "miner.zk-prover-mode can only be 1 or 2" exit 1 fi @@ -72,6 +72,38 @@ if [ ! -e ${zkey_file} ] || [ $(wc -c < ${zkey_file}) -ne ${zkey_size} ]; then fi fi + +# ZK prover implementation, 1: snarkjs, 2: go-rapidsnark. +zkp_impl=1 +i=1 +while [ $i -le $# ]; do + if [ "${!i}" = "--miner.zk-prover-impl" ]; then + j=$((i+1)) + zkp_impl="${!j}" + break + else + if echo "${!i}" | grep -qE -- "--miner\.zk-prover-impl=([0-9]+)"; then + zkp_impl=$(echo "${!i}" | sed -E 's/.*=([0-9]+)/\1/') + break + fi + fi + i=$((i+1)) +done + +if [ "$zkp_impl" != 1 ] && [ "$zkp_impl" != 2 ]; then + echo "miner.zk-prover-impl can only be 1 or 2" + exit 1 +fi + +echo "zk prover implementation is $zkp_impl" +if [ "$zkp_impl" = 1 ]; then + # install snarkjs if not + if ! [ "$(command -v snarkjs)" ]; then + echo "snarkjs not found, start installing..." + npm install -g snarkjs + fi +fi + executable="./build/bin/es-node" data_dir="./es-data" storage_file_0="$data_dir/shard-0.dat" From c1568cadb3e1215d09e73df29d282af6c5b3fcd4 Mon Sep 17 00:00:00 2001 From: syntrust Date: Thu, 1 Feb 2024 17:43:07 +0800 Subject: [PATCH 23/45] use bash to support flags --- Dockerfile | 2 +- docker-compose.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 82f666a4..11ab096d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,7 +7,7 @@ RUN make # Pull ES node into a second stage deploy alpine container FROM alpine:latest COPY --from=builder /es-node/build/ /es-node/build/ -RUN apk add --no-cache curl grep libstdc++ gcompat libgomp +RUN apk add --no-cache bash curl grep libstdc++ gcompat libgomp # Entrypoint COPY --from=builder /es-node/run.sh /es-node/ diff --git a/docker-compose.yaml b/docker-compose.yaml index c0a42245..9bd31192 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -11,6 +11,6 @@ services: environment: - ES_NODE_STORAGE_MINER=${ES_NODE_STORAGE_MINER} - ES_NODE_SIGNER_PRIVATE_KEY=${ES_NODE_SIGNER_PRIVATE_KEY} - command: ["sh", "-c", "/es-node/run.sh --miner.zk-prover-impl=2"] + command: ["bash", "-c", "/es-node/run.sh --miner.zk-prover-impl=2"] container_name: es tty: true From db49a85dd1014d510e614462a2a56f74f8ff6866 Mon Sep 17 00:00:00 2001 From: syntrust Date: Thu, 1 Feb 2024 17:43:25 +0800 Subject: [PATCH 24/45] use bash to support flags --- run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/run.sh b/run.sh index 0b8f8ecc..a6c123e0 100755 --- a/run.sh +++ b/run.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # usage: # env ES_NODE_STORAGE_MINER= ES_NODE_SIGNER_PRIVATE_KEY= ./run.sh From 716a139a70e80fb588e5541ebc4d7b1c0f7bc819 Mon Sep 17 00:00:00 2001 From: syntrust Date: Thu, 1 Feb 2024 17:43:42 +0800 Subject: [PATCH 25/45] fixes --- GUIDE.md | 2 +- ethstorage/miner/cli.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/GUIDE.md b/GUIDE.md index 81be1c28..f345b378 100644 --- a/GUIDE.md +++ b/GUIDE.md @@ -109,7 +109,7 @@ chmod +x run.sh && env ES_NODE_STORAGE_MINER= ES_NODE_SIGNER_PRIVATE_KEY= With source code, you also have the option to build a Docker image by yourself and run an es-node container: ```sh -env ES_NODE_STORAGE_MINER= ES_NODE_SIGNER_PRIVATE_KEY= docker compose up +env ES_NODE_STORAGE_MINER= ES_NODE_SIGNER_PRIVATE_KEY= docker-compose up ``` If you want to run Docker container in the background and keep all the logs: ```sh diff --git a/ethstorage/miner/cli.go b/ethstorage/miner/cli.go index 29868889..ecd56ff8 100644 --- a/ethstorage/miner/cli.go +++ b/ethstorage/miner/cli.go @@ -49,7 +49,7 @@ func CLIFlags(envPrefix string) []cli.Flag { }, &types.BigFlag{ Name: MinimumProfitFlagName, - Usage: "Minimum profit for mining transactions", + Usage: "Minimum profit for mining transactions in wei", Value: DefaultConfig.MinimumProfit, EnvVar: rollup.PrefixEnvVar(envPrefix, "MIN_PROFIT"), }, From 061330838c7e3b96e1e97ca5aa477583a27c1772 Mon Sep 17 00:00:00 2001 From: syntrust Date: Fri, 2 Feb 2024 09:54:59 +0800 Subject: [PATCH 26/45] add node to docker --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 11ab096d..0342646c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,7 +7,7 @@ RUN make # Pull ES node into a second stage deploy alpine container FROM alpine:latest COPY --from=builder /es-node/build/ /es-node/build/ -RUN apk add --no-cache bash curl grep libstdc++ gcompat libgomp +RUN apk add --no-cache bash curl grep libstdc++ gcompat libgomp nodejs npm # Entrypoint COPY --from=builder /es-node/run.sh /es-node/ From 8cc3efb2df2f8f8f661ff216df1cec5ec70b288f Mon Sep 17 00:00:00 2001 From: syntrust Date: Fri, 2 Feb 2024 12:02:50 +0800 Subject: [PATCH 27/45] doc the flag --- GUIDE.md | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/GUIDE.md b/GUIDE.md index a6fdb3d8..7270340d 100644 --- a/GUIDE.md +++ b/GUIDE.md @@ -43,6 +43,14 @@ You can run es-node from a pre-built Docker image, a pre-built executable, or fr - If you prefer to build [from the source code](#from-source-code), you will also need to install Go besides Node.js and snarkjs. + ### About the option of zk prover implementation + +The `--miner.zk-prover-impl` flag specifies the type of zkSNARK implementation. + +Its default value is `1` which represents snarkjs. You have the option to override the flag and set it to `2` in order to utilize go-rapidsnark, which enhances the performance of zk proof generation on certain platforms, such as Ubuntu. + +Before overriding the option, be sure to [verify the corresponding dependencies](#install-rapidsnark-dependencies). + ## From pre-built executables Before running es-node from the pre-built executables, ensure that you have installed [Node.js](#install-nodejs) and [snarkjs](#install-snarkjs). @@ -162,6 +170,22 @@ nvm use 20 npm install -g snarkjs ``` +### Install RapidSNARK dependencies + +Check if `build-essential` and `libomp-dev packages` are installed on your Ubuntu system: + +``` +dpkg -l | grep build-essential +dpkg -l | grep libomp-dev +``` +Install the build-essential and libomp-dev packages if no information printed: + +``` +apt update +apt install build-essential +apt install libomp-dev +``` + ## Two phases after es-node launch After the launch of ES node, it basically goes through two main stages. @@ -219,7 +243,7 @@ However, this high-intensity processing occurs primarily when large volumes of d If there is a need to conserve CPU power anyway, you can tune down the values of syncing performance related flags, namely `--p2p.sync.concurrency` and `--p2p.fill-empty.concurrency`. See [here](#how-to-tune-the-performance-of-syncing) for detailed information. -### What does it means when the log shows "The nonces are exhausted in this slot" +### What does it means when the log shows "The nonces are exhausted in this slot"? When you see "The nonces are exhausted in this slot...", it indicates that your node has successfully completed all the sampling tasks within a slot, and you do not need to do anything about it. From db3b9d146d1e8c3c5a25e3bade7f4038ebea2597 Mon Sep 17 00:00:00 2001 From: syntrust Date: Fri, 2 Feb 2024 12:43:43 +0800 Subject: [PATCH 28/45] test result --- ethstorage/prover/README.md | 48 ++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/ethstorage/prover/README.md b/ethstorage/prover/README.md index 74698035..034799eb 100644 --- a/ethstorage/prover/README.md +++ b/ethstorage/prover/README.md @@ -27,4 +27,50 @@ Go-rapidsnark also provides the go version of the witness calculator, so that ou We also need to investigate the gnark to decide whether we want to choose it or rapidsnark, but at least we have a better alternative than snarkjs -source: https://github.com/ethstorage/go-ethstorage/pull/14#issuecomment-1590816080 \ No newline at end of file +source: https://github.com/ethstorage/go-ethstorage/pull/14#issuecomment-1590816080 + + + +### Performance updates + +1. Tests on MacOS amd64 show no performance gain of go-rapidsnark. + + Implementation | Proof per sample (mode 1) | Proof for 2 samples (mode 2) +-- | -- | -- +snarkjs | 43.8 | 60.1 +go-rapidsnark + wazero.Circom2WZWitnessCalculator | 47.1 | 82.3 +go-rapidsnark + wasmer.Circom2WitnessCalculator | 49.5 | 101.8 + +Note rapidsnark supports 2 witness calculator implementations which `wazero` wins, so `wazero` is used with go-rapidsnark in below tests. + +2. Tests on MacOS arm64 (m3) show a slight performance gain of go-rapidsnark. + + Implementation | Proof per sample (mode 1) | Proof for 2 samples (mode 2) +-- | -- | -- +snarkjs | 16.2 | 31.7 +go-rapidsnark| 15.1 | 28.0 + +3. Ubuntu (AX101) + + Implementation | Proof per sample (mode 1) | Proof for 2 samples (mode 2) +-- | -- | -- +snarkjs | 12.6 | 24.4 +go-rapidsnark | 5.7 | 14.1 + +4. With `-tags rapidsnark_asm` AX101 has an obvious improvement, esp. mode2: + + Implementation | Proof per sample (mode 1) | Proof for 2 samples (mode 2) +-- | -- | -- +go-rapidsnark | 5.7 | 14.1 +go-rapidsnark + `-tags rapidsnark_asm` | 4.6 | 8.2 + +But this is not the case for Mac. MacOS build has the optimization enabled according to [the go-rapidsnark doc](https://github.com/iden3/go-rapidsnark/tree/main/prover#performance-optimization-on-x86_64-hardware). + +5. Tests on MacOS amd64, comparing to rapidsnark (c++) + +Implementation|Proof per sample (mode 1)|Proof for 2 samples (mode 2) +-- | -- | -- +snarkjs | 43.8 | 60.1 | +go-rapidsnark| 47.1 | 82.3 | +rapidsnark| 8.2 | 16.7 | + From 7dc4d1abd7f01642d6976066a77fd9dea2f695e2 Mon Sep 17 00:00:00 2001 From: syntrust Date: Fri, 2 Feb 2024 15:56:03 +0800 Subject: [PATCH 29/45] add debug msg --- ethstorage/miner/l1_mining_api.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ethstorage/miner/l1_mining_api.go b/ethstorage/miner/l1_mining_api.go index 32e8e70d..65654531 100644 --- a/ethstorage/miner/l1_mining_api.go +++ b/ethstorage/miner/l1_mining_api.go @@ -154,6 +154,8 @@ func (m *l1MiningAPI) SubmitMinedResult(ctx context.Context, contract common.Add }) if err != nil { m.lg.Error("Estimate gas failed", "error", err.Error()) + curBlock, _ := m.BlockNumber(context.Background()) + m.lg.Warn("Query most recent block", "block", curBlock) return common.Hash{}, fmt.Errorf("failed to estimate gas: %w", err) } m.lg.Info("Estimated gas done", "gas", estimatedGas) From 7616d2228318cff344d763fbc01fee28bb05cbbf Mon Sep 17 00:00:00 2001 From: syntrust Date: Fri, 2 Feb 2024 19:40:11 +0800 Subject: [PATCH 30/45] add log --- ethstorage/miner/l1_mining_api.go | 4 ++-- ethstorage/miner/worker.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ethstorage/miner/l1_mining_api.go b/ethstorage/miner/l1_mining_api.go index 65654531..75b6b9b8 100644 --- a/ethstorage/miner/l1_mining_api.go +++ b/ethstorage/miner/l1_mining_api.go @@ -154,8 +154,8 @@ func (m *l1MiningAPI) SubmitMinedResult(ctx context.Context, contract common.Add }) if err != nil { m.lg.Error("Estimate gas failed", "error", err.Error()) - curBlock, _ := m.BlockNumber(context.Background()) - m.lg.Warn("Query most recent block", "block", curBlock) + curBlock, _ := m.HeaderByNumber(ctx, big.NewInt(rpc.LatestBlockNumber.Int64())) + m.lg.Warn("Query most recent block", "blockNumber", curBlock.Number, "blockTime", curBlock.Time, "blockHash", curBlock.Hash()) return common.Hash{}, fmt.Errorf("failed to estimate gas: %w", err) } m.lg.Info("Estimated gas done", "gas", estimatedGas) diff --git a/ethstorage/miner/worker.go b/ethstorage/miner/worker.go index c62a6905..07b53fed 100644 --- a/ethstorage/miner/worker.go +++ b/ethstorage/miner/worker.go @@ -171,7 +171,7 @@ func (w *worker) newWorkLoop() { if !w.isRunning() { break } - w.lg.Info("Updating tasks with L1 new head", "blockNumber", block.Number, "blockTime", block.Time, "now", uint64(time.Now().Unix())) + w.lg.Info("Updating tasks with L1 new head", "blockNumber", block.Number, "blockTime", block.Time, "blockHash", block.Hash, "now", uint64(time.Now().Unix())) // TODO suspend mining if: // 1) a mining tx is already submitted; or // 2) if the last mining time is too close (the reward is not enough). From 7dc1563b270f1ea8c5b3292523f3cf72826b7c76 Mon Sep 17 00:00:00 2001 From: syntrust Date: Sun, 4 Feb 2024 11:54:54 +0800 Subject: [PATCH 31/45] more info for faild tx --- ethstorage/miner/l1_mining_api.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ethstorage/miner/l1_mining_api.go b/ethstorage/miner/l1_mining_api.go index 75b6b9b8..0333e263 100644 --- a/ethstorage/miner/l1_mining_api.go +++ b/ethstorage/miner/l1_mining_api.go @@ -155,7 +155,9 @@ func (m *l1MiningAPI) SubmitMinedResult(ctx context.Context, contract common.Add if err != nil { m.lg.Error("Estimate gas failed", "error", err.Error()) curBlock, _ := m.HeaderByNumber(ctx, big.NewInt(rpc.LatestBlockNumber.Int64())) - m.lg.Warn("Query most recent block", "blockNumber", curBlock.Number, "blockTime", curBlock.Time, "blockHash", curBlock.Hash()) + if curBlock != nil { + m.lg.Info("Query most recent block", "blockNumber", curBlock.Number, "blockTime", curBlock.Time, "blockHash", curBlock.Hash()) + } return common.Hash{}, fmt.Errorf("failed to estimate gas: %w", err) } m.lg.Info("Estimated gas done", "gas", estimatedGas) @@ -205,7 +207,7 @@ func (m *l1MiningAPI) SubmitMinedResult(ctx context.Context, contract common.Add } err = m.SendTransaction(ctx, signedTx) if err != nil { - m.lg.Error("Send tx failed", "error", err) + m.lg.Error("Send tx failed", "txNonce", nonce, "gasPrice", gasPrice, "error", err) return common.Hash{}, err } m.lg.Info("Submit mined result done", "shard", rst.startShardId, "block", rst.blockNumber, From 92a4c317ce8ff3bbb23d45c5e1bdadf60bd89c9a Mon Sep 17 00:00:00 2001 From: syntrust Date: Sun, 4 Feb 2024 16:03:26 +0800 Subject: [PATCH 32/45] minor --- ethstorage/miner/l1_mining_api.go | 4 ---- ethstorage/prover/zk_prover.go | 4 ++-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/ethstorage/miner/l1_mining_api.go b/ethstorage/miner/l1_mining_api.go index 0333e263..47e88c91 100644 --- a/ethstorage/miner/l1_mining_api.go +++ b/ethstorage/miner/l1_mining_api.go @@ -154,10 +154,6 @@ func (m *l1MiningAPI) SubmitMinedResult(ctx context.Context, contract common.Add }) if err != nil { m.lg.Error("Estimate gas failed", "error", err.Error()) - curBlock, _ := m.HeaderByNumber(ctx, big.NewInt(rpc.LatestBlockNumber.Int64())) - if curBlock != nil { - m.lg.Info("Query most recent block", "blockNumber", curBlock.Number, "blockTime", curBlock.Time, "blockHash", curBlock.Hash()) - } return common.Hash{}, fmt.Errorf("failed to estimate gas: %w", err) } m.lg.Info("Estimated gas done", "gas", estimatedGas) diff --git a/ethstorage/prover/zk_prover.go b/ethstorage/prover/zk_prover.go index b3dc092f..b5e29d2a 100644 --- a/ethstorage/prover/zk_prover.go +++ b/ethstorage/prover/zk_prover.go @@ -68,7 +68,7 @@ func (p *ZKProver) GenerateZKProofRaw(encodingKeys []common.Hash, sampleIdxs []u start := time.Now() defer func(start time.Time) { dur := time.Since(start) - p.lg.Info("Generate zk proof done", "sampleIdx", sampleIdxs, "took(sec)", dur.Seconds()) + p.lg.Info("Generate zk proof done", "sampleIdx", sampleIdxs, "timeUsed(s)", dur.Seconds()) }(start) pubInputs, err := p.GenerateInputs(encodingKeys, sampleIdxs) @@ -123,7 +123,7 @@ func (p *ZKProver) GenerateZKProofPerSample(encodingKey common.Hash, sampleIdx u start := time.Now() defer func(start time.Time) { dur := time.Since(start) - p.lg.Info("Generate zk proof done", "sampleIdx", sampleIdx, "took(sec)", dur.Seconds()) + p.lg.Info("Generate zk proof done", "sampleIdx", sampleIdx, "timeUsed(s)", dur.Seconds()) }(start) pubInput, err := p.GenerateInput(encodingKey, sampleIdx) From ef4267de17de301e55bb7a7af3dd44f3915e500f Mon Sep 17 00:00:00 2001 From: syntrust Date: Sun, 4 Feb 2024 16:03:44 +0800 Subject: [PATCH 33/45] wait longer for confirm --- ethstorage/miner/worker.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethstorage/miner/worker.go b/ethstorage/miner/worker.go index 07b53fed..a5a05cba 100644 --- a/ethstorage/miner/worker.go +++ b/ethstorage/miner/worker.go @@ -26,7 +26,7 @@ const ( sampleSizeBits = 5 // 32 bytes // always use new block hash to mine for each slot mineTimeOut = 12 // seconds - miningTransactionTimeout = 25 // seconds + miningTransactionTimeout = 50 // seconds ) var ( From 5910b95072443474fcc63f5e8676e7abd394f977 Mon Sep 17 00:00:00 2001 From: syntrust Date: Sun, 4 Feb 2024 17:02:52 +0800 Subject: [PATCH 34/45] avoid blockNumber == block.number --- ethstorage/miner/miner.go | 1 + ethstorage/miner/worker.go | 22 +++++++++++++++------- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/ethstorage/miner/miner.go b/ethstorage/miner/miner.go index d582cb85..bc297dba 100644 --- a/ethstorage/miner/miner.go +++ b/ethstorage/miner/miner.go @@ -24,6 +24,7 @@ type L1API interface { GetMiningInfo(ctx context.Context, contract common.Address, shardIdx uint64) (*miningInfo, error) SubmitMinedResult(ctx context.Context, contract common.Address, rst result, config Config) (common.Hash, error) GetDataHashes(ctx context.Context, contract common.Address, kvIdxes []uint64) ([]common.Hash, error) + BlockNumber(ctx context.Context) (uint64, error) } type MiningProver interface { diff --git a/ethstorage/miner/worker.go b/ethstorage/miner/worker.go index a5a05cba..873361f0 100644 --- a/ethstorage/miner/worker.go +++ b/ethstorage/miner/worker.go @@ -20,12 +20,11 @@ import ( ) const ( - chainHeadChanSize = 1 - taskQueueSize = 1 - resultQueueSize = 10 - sampleSizeBits = 5 // 32 bytes - // always use new block hash to mine for each slot - mineTimeOut = 12 // seconds + chainHeadChanSize = 1 + taskQueueSize = 1 + resultQueueSize = 10 + sampleSizeBits = 5 // 32 bytes + slot = 12 // seconds miningTransactionTimeout = 50 // seconds ) @@ -306,6 +305,14 @@ func (w *worker) resultLoop() { continue } w.lg.Info("Mining result loop get result", "shard", result.startShardId, "block", result.blockNumber, "nonce", result.nonce) + latest, err := w.l1API.BlockNumber(context.Background()) + if err != nil { + w.lg.Warn("Failed to get L1 block number", "error", err.Error()) + } + // to avoid blockNumber == block.number in the contract + if latest == result.blockNumber.Uint64() { + time.Sleep(slot * time.Second) + } txHash, err := w.l1API.SubmitMinedResult( context.Background(), w.storageMgr.ContractAddress(), @@ -393,7 +400,8 @@ func (w *worker) mineTask(t *taskItem) (bool, error) { nonce := t.nonceStart w.lg.Debug("Mining task started", "shard", t.shardIdx, "thread", t.thread, "block", t.blockNumber, "nonces", fmt.Sprintf("%d~%d", t.nonceStart, t.nonceEnd)) for w.isRunning() { - if time.Since(startTime).Seconds() > mineTimeOut { + // always use new randao to mine for each slot + if time.Since(startTime).Seconds() > slot { if t.thread == 0 { nonceTriedTotal := (nonce - t.nonceStart) * w.config.ThreadsPerShard w.lg.Warn("Mining tasks timed out", "shard", t.shardIdx, "block", t.blockNumber, From 39e5dd28bf5dfe412b59b560dfed250dac04e8fa Mon Sep 17 00:00:00 2001 From: syntrust Date: Sun, 4 Feb 2024 17:13:14 +0800 Subject: [PATCH 35/45] add log --- ethstorage/miner/worker.go | 1 + 1 file changed, 1 insertion(+) diff --git a/ethstorage/miner/worker.go b/ethstorage/miner/worker.go index 873361f0..2c8a7d65 100644 --- a/ethstorage/miner/worker.go +++ b/ethstorage/miner/worker.go @@ -311,6 +311,7 @@ func (w *worker) resultLoop() { } // to avoid blockNumber == block.number in the contract if latest == result.blockNumber.Uint64() { + w.lg.Info("Will wait a slot for the block number to increase") time.Sleep(slot * time.Second) } txHash, err := w.l1API.SubmitMinedResult( From 182480ec35cdcf78003044463bd29433d797d27c Mon Sep 17 00:00:00 2001 From: syntrust Date: Wed, 7 Feb 2024 17:32:41 +0800 Subject: [PATCH 36/45] fix comments and refactor --- Dockerfile | 3 +- GUIDE.md | 6 ++- README.md | 3 +- ethstorage/prover/kzg_poseidon_prover.go | 10 +---- ethstorage/prover/utils.go | 39 ++++++++++++++++++ ethstorage/prover/zk_prover.go | 52 +----------------------- ethstorage/prover/zk_prover_go.go | 42 +------------------ integration_tests/zk_prover2_test.go | 2 +- integration_tests/zk_prover_test.go | 2 +- run-docker.sh | 3 +- 10 files changed, 56 insertions(+), 106 deletions(-) diff --git a/Dockerfile b/Dockerfile index 0342646c..b9b46dbe 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,7 +7,8 @@ RUN make # Pull ES node into a second stage deploy alpine container FROM alpine:latest COPY --from=builder /es-node/build/ /es-node/build/ -RUN apk add --no-cache bash curl grep libstdc++ gcompat libgomp nodejs npm +RUN apk add --no-cache bash libstdc++ gcompat libgomp nodejs npm +RUN npm install -g snarkjs # Entrypoint COPY --from=builder /es-node/run.sh /es-node/ diff --git a/GUIDE.md b/GUIDE.md index 289c881b..226711f0 100644 --- a/GUIDE.md +++ b/GUIDE.md @@ -49,7 +49,7 @@ The `--miner.zk-prover-impl` flag specifies the type of zkSNARK implementation. Its default value is `1` which represents snarkjs. You have the option to override the flag and set it to `2` in order to utilize go-rapidsnark, which enhances the performance of zk proof generation on certain platforms, such as Ubuntu. -Before overriding the option, be sure to [verify the corresponding dependencies](#install-rapidsnark-dependencies). +If you want to build an es-node with go-rapidsnark on Ubuntu, be sure to [verify the corresponding dependencies](#install-rapidsnark-dependencies). ## From pre-built executables @@ -87,8 +87,10 @@ docker run --name es -d \ -p 9222:9222 \ -p 30305:30305/udp \ --entrypoint /es-node/run.sh \ - ghcr.io/ethstorage/es-node:v0.1.6 + ghcr.io/ethstorage/es-node:v0.1.6 \ + --miner.zk-prover-impl 2 ``` +Note that ` --miner.zk-prover-impl 2` is used to generate zk proofs using go-rapidsnark instead of snarkjs for better performance. You can check docker logs using the following command: ```sh diff --git a/README.md b/README.md index 6c14ebaa..fc6a624d 100644 --- a/README.md +++ b/README.md @@ -83,9 +83,8 @@ The full list of options that you can use to configure an es-node are as follows |`--miner.min-profit`|Minimum profit for mining transactions|`0`|| |`--miner.priority-gas-price`|Priority gas price for mining transactions||| |`--miner.threads-per-shard`|Number of threads per shard|`runtime.NumCPU() x 2`|| -|`--miner.zk-prover-version value`|ZK prover version, 1: one proof per sample, 2: one proof for multiple samples|`2`|| |`--miner.zk-prover-mode`|ZK prover mode, 1: one proof per sample, 2: one proof for multiple samples|`2`|| -|`--miner.zk-prover-impl`|ZK prover implmentation, 1: snarkjs, 2: go-rapidsnark|`1`|| +|`--miner.zk-prover-impl`|ZK prover implementation, 1: snarkjs, 2: go-rapidsnark|`1`|| |`--miner.zk-working-dir`|Path to the snark_lib folder|`build/bin`|| |`--miner.zkey`|zkey file name which should be put in the snark_lib folder|`blob_poseidon2.zkey`|| |`--network`|Predefined L1 network selection. Available networks: devnet||| diff --git a/ethstorage/prover/kzg_poseidon_prover.go b/ethstorage/prover/kzg_poseidon_prover.go index 8b4685e9..dd396392 100644 --- a/ethstorage/prover/kzg_poseidon_prover.go +++ b/ethstorage/prover/kzg_poseidon_prover.go @@ -17,12 +17,8 @@ import ( type IZKProver interface { // Generate a zk proof for the given encoding keys and samples and return proof and masks (mode 2) GenerateZKProof(encodingKeys []common.Hash, sampleIdxs []uint64) ([]byte, []*big.Int, error) - // Generate public inputs (mode 2) - GenerateInputs(encodingKeys []common.Hash, sampleIdxs []uint64) ([]byte, error) // Generate a zk proof for a given sample (mode 1) GenerateZKProofPerSample(encodingKey common.Hash, sampleIdx uint64) ([]byte, *big.Int, error) - // Generate public input (mode 1) - GenerateInput(encodingKey common.Hash, sampleIdx uint64) ([]byte, error) // Generate ZK Proof for the given encoding keys and samples and return proof and all publics (mode 2) GenerateZKProofRaw(encodingKeys []common.Hash, sampleIdxs []uint64) ([]byte, []*big.Int, error) } @@ -38,7 +34,6 @@ type KZGPoseidonProver struct { zkProverImpl uint64 libDir string zkey string - wasm string lg log.Logger } @@ -81,7 +76,6 @@ func NewKZGPoseidonProver(workingDir, zkeyFileName string, zkProverMode, zkProve zkProverImpl: zkProverImpl, libDir: libDir, zkey: zkeyFileName, - wasm: wasmName, lg: lg, } } @@ -132,10 +126,10 @@ func (p *KZGPoseidonProver) GetStorageProof(data [][]byte, encodingKeys []common func (p *KZGPoseidonProver) getZKProver() (IZKProver, error) { if p.zkProverImpl == 1 { - return NewZKProver(filepath.Dir(p.libDir), p.zkey, p.wasm, p.lg), nil + return NewZKProver(filepath.Dir(p.libDir), p.zkey, WasmName, p.lg), nil } if p.zkProverImpl == 2 { - return NewZKProverGo(p.libDir, p.zkey, p.wasm, p.lg) + return NewZKProverGo(p.libDir, p.zkey, Wasm2Name, p.lg) } return nil, fmt.Errorf("invalid zk prover implementation: %d", p.zkProverImpl) } diff --git a/ethstorage/prover/utils.go b/ethstorage/prover/utils.go index cd63ebc3..ae1fd402 100644 --- a/ethstorage/prover/utils.go +++ b/ethstorage/prover/utils.go @@ -9,7 +9,11 @@ import ( "math/big" "os" + "github.com/consensys/gnark-crypto/ecc/bn254/fr" + "github.com/crate-crypto/go-proto-danksharding-crypto/eth" "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/iden3/go-rapidsnark/types" ) @@ -232,3 +236,38 @@ func readMaskFrom(publicFile string) (*big.Int, error) { } return readMask(dat) } + +// Generate public inputs (mode 2) +func GenerateInputs(encodingKeys []common.Hash, sampleIdxs []uint64) ([]byte, error) { + var encodingKeyModStr, xInStr []string + for i, sampleIdx := range sampleIdxs { + var b fr.Element + var exp big.Int + exp.Div(exp.Sub(fr.Modulus(), common.Big1), big.NewInt(int64(eth.FieldElementsPerBlob))) + ru := b.Exp(*b.SetInt64(5), &exp) + xIn := ru.Exp(*ru, new(big.Int).SetUint64(sampleIdx)) + xInStr = append(xInStr, xIn.String()) + encodingKeyMod := fr.Modulus().Mod(encodingKeys[i].Big(), fr.Modulus()) + encodingKeyModStr = append(encodingKeyModStr, hexutil.Encode(encodingKeyMod.Bytes())) + } + inputObj := InputPairV2{ + EncodingKeyIn: encodingKeyModStr, + XIn: xInStr, + } + return json.Marshal(inputObj) +} + +// Generate public input (mode 1) +func GenerateInput(encodingKey common.Hash, sampleIdx uint64) ([]byte, error) { + var b fr.Element + var exp big.Int + exp.Div(exp.Sub(fr.Modulus(), common.Big1), big.NewInt(int64(eth.FieldElementsPerBlob))) + ru := b.Exp(*b.SetInt64(5), &exp) + xIn := ru.Exp(*ru, big.NewInt(int64(sampleIdx))) + encodingKeyMod := fr.Modulus().Mod(encodingKey.Big(), fr.Modulus()) + inputObj := InputPair{ + EncodingKeyIn: hexutil.Encode(encodingKeyMod.Bytes()), + XIn: xIn.String(), + } + return json.Marshal(inputObj) +} diff --git a/ethstorage/prover/zk_prover.go b/ethstorage/prover/zk_prover.go index b5e29d2a..d1fcfeb6 100644 --- a/ethstorage/prover/zk_prover.go +++ b/ethstorage/prover/zk_prover.go @@ -4,7 +4,6 @@ package prover import ( - "encoding/json" "fmt" "math/big" "os" @@ -12,10 +11,8 @@ import ( "path/filepath" "time" - "github.com/consensys/gnark-crypto/ecc/bn254/fr" "github.com/crate-crypto/go-proto-danksharding-crypto/eth" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" ) @@ -71,7 +68,7 @@ func (p *ZKProver) GenerateZKProofRaw(encodingKeys []common.Hash, sampleIdxs []u p.lg.Info("Generate zk proof done", "sampleIdx", sampleIdxs, "timeUsed(s)", dur.Seconds()) }(start) - pubInputs, err := p.GenerateInputs(encodingKeys, sampleIdxs) + pubInputs, err := GenerateInputs(encodingKeys, sampleIdxs) if err != nil { p.lg.Error("Generate inputs failed", "error", err) return nil, nil, err @@ -90,31 +87,6 @@ func (p *ZKProver) GenerateZKProofRaw(encodingKeys []common.Hash, sampleIdxs []u return proof, publics, nil } -func (p *ZKProver) GenerateInputs(encodingKeys []common.Hash, sampleIdxs []uint64) ([]byte, error) { - var encodingKeyModStr, xInStr []string - for i, sampleIdx := range sampleIdxs { - var b fr.Element - var exp big.Int - exp.Div(exp.Sub(fr.Modulus(), common.Big1), big.NewInt(int64(eth.FieldElementsPerBlob))) - ru := b.Exp(*b.SetInt64(5), &exp) - xIn := ru.Exp(*ru, new(big.Int).SetUint64(sampleIdx)) - xInStr = append(xInStr, xIn.String()) - encodingKeyMod := fr.Modulus().Mod(encodingKeys[i].Big(), fr.Modulus()) - encodingKeyModStr = append(encodingKeyModStr, hexutil.Encode(encodingKeyMod.Bytes())) - } - inputObj := InputPairV2{ - EncodingKeyIn: encodingKeyModStr, - XIn: xInStr, - } - inputs, err := json.Marshal(inputObj) - if err != nil { - p.lg.Error("Encode input failed", "error", err) - return nil, err - } - p.lg.Debug("Generate zk proof", "input", inputObj) - return inputs, nil -} - func (p *ZKProver) GenerateZKProofPerSample(encodingKey common.Hash, sampleIdx uint64) ([]byte, *big.Int, error) { p.lg.Debug("Generate zk proof", "encodingKey", encodingKey.Hex(), "sampleIdx", sampleIdx) if int(sampleIdx) >= eth.FieldElementsPerBlob { @@ -126,7 +98,7 @@ func (p *ZKProver) GenerateZKProofPerSample(encodingKey common.Hash, sampleIdx u p.lg.Info("Generate zk proof done", "sampleIdx", sampleIdx, "timeUsed(s)", dur.Seconds()) }(start) - pubInput, err := p.GenerateInput(encodingKey, sampleIdx) + pubInput, err := GenerateInput(encodingKey, sampleIdx) if err != nil { p.lg.Error("Generate input failed", "error", err) return nil, nil, err @@ -146,26 +118,6 @@ func (p *ZKProver) GenerateZKProofPerSample(encodingKey common.Hash, sampleIdx u return proof, mask, nil } -func (p *ZKProver) GenerateInput(encodingKey common.Hash, sampleIdx uint64) ([]byte, error) { - var b fr.Element - var exp big.Int - exp.Div(exp.Sub(fr.Modulus(), common.Big1), big.NewInt(int64(eth.FieldElementsPerBlob))) - ru := b.Exp(*b.SetInt64(5), &exp) - xIn := ru.Exp(*ru, big.NewInt(int64(sampleIdx))) - encodingKeyMod := fr.Modulus().Mod(encodingKey.Big(), fr.Modulus()) - inputObj := InputPair{ - EncodingKeyIn: hexutil.Encode(encodingKeyMod.Bytes()), - XIn: xIn.String(), - } - input, err := json.Marshal(inputObj) - if err != nil { - p.lg.Error("Encode input failed", "error", err) - return nil, err - } - p.lg.Debug("Generate zk proof", "input", inputObj) - return input, nil -} - func (p *ZKProver) prove(dir string, pubInputs []byte) ([]byte, string, error) { temp := crypto.Keccak256Hash([]byte(dir)) buildDir := filepath.Join(p.dir, snarkBuildDir, common.Bytes2Hex(temp[:])) diff --git a/ethstorage/prover/zk_prover_go.go b/ethstorage/prover/zk_prover_go.go index cc040463..9a5b949f 100644 --- a/ethstorage/prover/zk_prover_go.go +++ b/ethstorage/prover/zk_prover_go.go @@ -4,17 +4,14 @@ package prover import ( - "encoding/json" "fmt" "math/big" "os" "path/filepath" "time" - "github.com/consensys/gnark-crypto/ecc/bn254/fr" "github.com/crate-crypto/go-proto-danksharding-crypto/eth" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/log" "github.com/iden3/go-rapidsnark/prover" "github.com/iden3/go-rapidsnark/witness/v2" @@ -75,7 +72,7 @@ func (p *ZKProverGo) GenerateZKProofRaw(encodingKeys []common.Hash, sampleIdxs [ p.lg.Info("Generate zk proof done", "sampleIdx", sampleIdxs, "timeUsed(s)", dur.Seconds()) }(start) - inputBytes, err := p.GenerateInputs(encodingKeys, sampleIdxs) + inputBytes, err := GenerateInputs(encodingKeys, sampleIdxs) if err != nil { p.lg.Error("Generate inputs failed", "error", err) return nil, nil, err @@ -93,26 +90,6 @@ func (p *ZKProverGo) GenerateZKProofRaw(encodingKeys []common.Hash, sampleIdxs [ return proof, publics, nil } -func (p *ZKProverGo) GenerateInputs(encodingKeys []common.Hash, sampleIdxs []uint64) ([]byte, error) { - var encodingKeyModStr, xInStr []string - for i, sampleIdx := range sampleIdxs { - var b fr.Element - var exp big.Int - exp.Div(exp.Sub(fr.Modulus(), common.Big1), big.NewInt(int64(eth.FieldElementsPerBlob))) - ru := b.Exp(*b.SetInt64(5), &exp) - xIn := ru.Exp(*ru, new(big.Int).SetUint64(sampleIdx)) - xInStr = append(xInStr, xIn.String()) - encodingKeyMod := fr.Modulus().Mod(encodingKeys[i].Big(), fr.Modulus()) - encodingKeyModStr = append(encodingKeyModStr, hexutil.Encode(encodingKeyMod.Bytes())) - } - inputObj := InputPairV2{ - EncodingKeyIn: encodingKeyModStr, - XIn: xInStr, - } - p.lg.Debug("Generate zk proof", "input", inputObj) - return json.Marshal(inputObj) -} - func (p *ZKProverGo) GenerateZKProofPerSample(encodingKey common.Hash, sampleIdx uint64) ([]byte, *big.Int, error) { p.lg.Debug("Generate zk proof", "encodingKey", encodingKey.Hex(), "sampleIdx", sampleIdx) if int(sampleIdx) >= eth.FieldElementsPerBlob { @@ -124,7 +101,7 @@ func (p *ZKProverGo) GenerateZKProofPerSample(encodingKey common.Hash, sampleIdx p.lg.Info("Generate zk proof", "sampleIdx", sampleIdx, "timeUsed(s)", dur.Seconds()) }(start) - inputBytes, err := p.GenerateInput(encodingKey, sampleIdx) + inputBytes, err := GenerateInput(encodingKey, sampleIdx) if err != nil { p.lg.Error("Generate inputs failed", "error", err) return nil, nil, err @@ -142,21 +119,6 @@ func (p *ZKProverGo) GenerateZKProofPerSample(encodingKey common.Hash, sampleIdx return proof, mask, nil } -func (p *ZKProverGo) GenerateInput(encodingKey common.Hash, sampleIdx uint64) ([]byte, error) { - var b fr.Element - var exp big.Int - exp.Div(exp.Sub(fr.Modulus(), common.Big1), big.NewInt(int64(eth.FieldElementsPerBlob))) - ru := b.Exp(*b.SetInt64(5), &exp) - xIn := ru.Exp(*ru, big.NewInt(int64(sampleIdx))) - encodingKeyMod := fr.Modulus().Mod(encodingKey.Big(), fr.Modulus()) - inputObj := InputPair{ - EncodingKeyIn: hexutil.Encode(encodingKeyMod.Bytes()), - XIn: xIn.String(), - } - p.lg.Debug("Generate zk proof", "input", inputObj) - return json.Marshal(inputObj) -} - func (p *ZKProverGo) prove(inputBytes []byte) ([]byte, string, error) { parsedInputs, err := witness.ParseInputs(inputBytes) if err != nil { diff --git a/integration_tests/zk_prover2_test.go b/integration_tests/zk_prover2_test.go index 39b84f05..775bc6dd 100644 --- a/integration_tests/zk_prover2_test.go +++ b/integration_tests/zk_prover2_test.go @@ -57,7 +57,7 @@ func TestZKProver_GenerateZKProof(t *testing.T) { for i, p := range prvs { t.Run(fmt.Sprintf("zk test %d", i), func(t *testing.T) { - inputsBytes, err := p.GenerateInputs(encodingKeys, sampleIdxs) + inputsBytes, err := prover.GenerateInputs(encodingKeys, sampleIdxs) if err != nil { t.Errorf("ZKProver.GenerateInputs() error = %v", err) return diff --git a/integration_tests/zk_prover_test.go b/integration_tests/zk_prover_test.go index 8d16b748..afb0dc43 100644 --- a/integration_tests/zk_prover_test.go +++ b/integration_tests/zk_prover_test.go @@ -79,7 +79,7 @@ func TestZKProver_GenerateZKProofPerSample(t *testing.T) { for _, p := range prvs { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - inputBytes, err := p.GenerateInput(tt.args.encodingKey, tt.args.sampleIdx) + inputBytes, err := prover.GenerateInput(tt.args.encodingKey, tt.args.sampleIdx) if err != nil { t.Errorf("ZKProver.GenerateInput() error = %v", err) return diff --git a/run-docker.sh b/run-docker.sh index 755673ff..dc948435 100755 --- a/run-docker.sh +++ b/run-docker.sh @@ -50,7 +50,8 @@ else -p 30305:30305/udp \ -d \ --entrypoint /es-node/run.sh \ - $image_name + $image_name \ + --miner.zk-prover-impl 2 echo "container $container_name started" fi fi From cfa45f427d872e5742d1a5d79c6ca8ace21ec839 Mon Sep 17 00:00:00 2001 From: syntrust Date: Wed, 7 Feb 2024 17:59:03 +0800 Subject: [PATCH 37/45] avoid empty slots --- ethstorage/miner/worker.go | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/ethstorage/miner/worker.go b/ethstorage/miner/worker.go index 2c8a7d65..e2851420 100644 --- a/ethstorage/miner/worker.go +++ b/ethstorage/miner/worker.go @@ -305,14 +305,18 @@ func (w *worker) resultLoop() { continue } w.lg.Info("Mining result loop get result", "shard", result.startShardId, "block", result.blockNumber, "nonce", result.nonce) - latest, err := w.l1API.BlockNumber(context.Background()) - if err != nil { - w.lg.Warn("Failed to get L1 block number", "error", err.Error()) - } - // to avoid blockNumber == block.number in the contract - if latest == result.blockNumber.Uint64() { - w.lg.Info("Will wait a slot for the block number to increase") - time.Sleep(slot * time.Second) + // check block number to avoid `blockNumber == block.number` in the contract, loop for 5 times in case of empty slots + for i := 0; i < 5; i++ { + latest, err := w.l1API.BlockNumber(context.Background()) + if err != nil { + w.lg.Warn("Failed to get L1 block number", "error", err.Error()) + continue + } + if latest == result.blockNumber.Uint64() { + w.lg.Info("Will wait a slot for the block number to increase") + time.Sleep(slot * time.Second) + } + break } txHash, err := w.l1API.SubmitMinedResult( context.Background(), From 79cf90b4e64f2de97bce3da21b443b266298da07 Mon Sep 17 00:00:00 2001 From: syntrust Date: Wed, 7 Feb 2024 18:34:04 +0800 Subject: [PATCH 38/45] fix err --- run-rpc.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/run-rpc.sh b/run-rpc.sh index 2a472851..12665611 100755 --- a/run-rpc.sh +++ b/run-rpc.sh @@ -9,7 +9,7 @@ storage_file_0="$data_dir/shard-0.dat" common_flags=" --datadir $data_dir \ --l1.rpc http://88.99.30.186:8545 \ - --storage.l1contract 0x804C520d3c084C805E37A35E90057Ac32831F96f \ + --storage.l1contract 0x804C520d3c084C805E37A35E90057Ac32831F96f" # init shard 0 es_node_init="init --shard_index 0" From 742508ed17c912f18b64b25f8e7c01f9e7cd205e Mon Sep 17 00:00:00 2001 From: syntrust Date: Wed, 7 Feb 2024 18:45:56 +0800 Subject: [PATCH 39/45] fix --- ethstorage/miner/worker.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ethstorage/miner/worker.go b/ethstorage/miner/worker.go index e2851420..5951988f 100644 --- a/ethstorage/miner/worker.go +++ b/ethstorage/miner/worker.go @@ -312,11 +312,11 @@ func (w *worker) resultLoop() { w.lg.Warn("Failed to get L1 block number", "error", err.Error()) continue } - if latest == result.blockNumber.Uint64() { - w.lg.Info("Will wait a slot for the block number to increase") - time.Sleep(slot * time.Second) + if latest > result.blockNumber.Uint64() { + break } - break + w.lg.Info("Will wait a slot for the block number to increase") + time.Sleep(slot * time.Second) } txHash, err := w.l1API.SubmitMinedResult( context.Background(), From e8249d8d8f07fd5d2e85a5553ad9ed4b09d6fabb Mon Sep 17 00:00:00 2001 From: syntrust Date: Tue, 20 Feb 2024 12:07:48 +0800 Subject: [PATCH 40/45] reduce redundancy --- ethstorage/prover/kzg_poseidon_prover.go | 5 ----- ethstorage/prover/utils.go | 3 +++ ethstorage/prover/zk_prover.go | 7 +------ ethstorage/prover/zk_prover_go.go | 7 +------ 4 files changed, 5 insertions(+), 17 deletions(-) diff --git a/ethstorage/prover/kzg_poseidon_prover.go b/ethstorage/prover/kzg_poseidon_prover.go index dd396392..0e11f28d 100644 --- a/ethstorage/prover/kzg_poseidon_prover.go +++ b/ethstorage/prover/kzg_poseidon_prover.go @@ -43,11 +43,6 @@ type KZGPoseidonProver struct { // zkProverMode specifies the mode of the zk prover, 1 for per sample, 2 for samples // zkProverImpl specifies the implementation of the snark prover, 1 for snarkjs, 2 for go-rapidsnark // lg specifies the logger to log the info -// returns a prover that can generate a combined KZG + zk proof -func NewKZGPoseidonProverWithLogger(workingDir, zkeyFileName string, zkProverMode, zkProverImpl uint64, lg log.Logger) KZGPoseidonProver { - return NewKZGPoseidonProver(workingDir, zkeyFileName, zkProverMode, zkProverImpl, lg) -} - // returns a prover that can generate a combined KZG + zk proof func NewKZGPoseidonProver(workingDir, zkeyFileName string, zkProverMode, zkProverImpl uint64, lg log.Logger) KZGPoseidonProver { // check dependencies when es-node starts diff --git a/ethstorage/prover/utils.go b/ethstorage/prover/utils.go index ae1fd402..59810e7b 100644 --- a/ethstorage/prover/utils.go +++ b/ethstorage/prover/utils.go @@ -241,6 +241,9 @@ func readMaskFrom(publicFile string) (*big.Int, error) { func GenerateInputs(encodingKeys []common.Hash, sampleIdxs []uint64) ([]byte, error) { var encodingKeyModStr, xInStr []string for i, sampleIdx := range sampleIdxs { + if int(sampleIdx) >= eth.FieldElementsPerBlob { + return nil, fmt.Errorf("chunk index out of scope: %d", sampleIdx) + } var b fr.Element var exp big.Int exp.Div(exp.Sub(fr.Modulus(), common.Big1), big.NewInt(int64(eth.FieldElementsPerBlob))) diff --git a/ethstorage/prover/zk_prover.go b/ethstorage/prover/zk_prover.go index d1fcfeb6..1d5ff7dc 100644 --- a/ethstorage/prover/zk_prover.go +++ b/ethstorage/prover/zk_prover.go @@ -56,18 +56,13 @@ func (p *ZKProver) GenerateZKProof(encodingKeys []common.Hash, sampleIdxs []uint } func (p *ZKProver) GenerateZKProofRaw(encodingKeys []common.Hash, sampleIdxs []uint64) ([]byte, []*big.Int, error) { - for i, idx := range sampleIdxs { - p.lg.Debug("Generate zk proof", "encodingKey", encodingKeys[i], "sampleIdx", sampleIdxs[i]) - if int(idx) >= eth.FieldElementsPerBlob { - return nil, nil, fmt.Errorf("chunk index out of scope: %d", idx) - } - } start := time.Now() defer func(start time.Time) { dur := time.Since(start) p.lg.Info("Generate zk proof done", "sampleIdx", sampleIdxs, "timeUsed(s)", dur.Seconds()) }(start) + p.lg.Debug("Generate zk proof", "encodingKeys", encodingKeys, "sampleIndexes", sampleIdxs) pubInputs, err := GenerateInputs(encodingKeys, sampleIdxs) if err != nil { p.lg.Error("Generate inputs failed", "error", err) diff --git a/ethstorage/prover/zk_prover_go.go b/ethstorage/prover/zk_prover_go.go index 9a5b949f..e665bd67 100644 --- a/ethstorage/prover/zk_prover_go.go +++ b/ethstorage/prover/zk_prover_go.go @@ -60,12 +60,7 @@ func (p *ZKProverGo) GenerateZKProof(encodingKeys []common.Hash, sampleIdxs []ui } func (p *ZKProverGo) GenerateZKProofRaw(encodingKeys []common.Hash, sampleIdxs []uint64) ([]byte, []*big.Int, error) { - for i, idx := range sampleIdxs { - p.lg.Debug("Generate zk proof", "encodingKey", encodingKeys[i], "sampleIdx", sampleIdxs[i]) - if int(idx) >= eth.FieldElementsPerBlob { - return nil, nil, fmt.Errorf("chunk index out of scope: %d", idx) - } - } + p.lg.Debug("Generate zk proof", "encodingKeys", encodingKeys, "sampleIndexes", sampleIdxs) start := time.Now() defer func(start time.Time) { dur := time.Since(start) From 916bf92d358832484c4241c3e1bcf0a0c3e30c8d Mon Sep 17 00:00:00 2001 From: syntrust Date: Tue, 20 Feb 2024 12:53:14 +0800 Subject: [PATCH 41/45] reduce redundancy --- integration_tests/common.go | 1 + integration_tests/zk_prover_test.go | 6 +----- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/integration_tests/common.go b/integration_tests/common.go index 002a7f87..d1e2d8a6 100644 --- a/integration_tests/common.go +++ b/integration_tests/common.go @@ -20,6 +20,7 @@ var ( l1Contract = common.HexToAddress(os.Getenv("ES_NODE_STORAGE_L1CONTRACT")) privateKey = os.Getenv("ES_NODE_SIGNER_PRIVATE_KEY") minerAddr = common.HexToAddress(os.Getenv("ES_NODE_STORAGE_MINER")) + prPath = "../ethstorage/prover" lg = esLog.NewLogger(esLog.CLIConfig{ Level: "debug", Format: "text", diff --git a/integration_tests/zk_prover_test.go b/integration_tests/zk_prover_test.go index afb0dc43..d5746b9a 100644 --- a/integration_tests/zk_prover_test.go +++ b/integration_tests/zk_prover_test.go @@ -28,11 +28,7 @@ import ( var zkp1Contract = common.HexToAddress(os.Getenv("ES_NODE_STORAGE_L1CONTRACT_ZKP1")) -const ( - l1ContractV1 = "0xc3208C27285ed9516F21a89053326Bb895DD78F7" - prPath = "../ethstorage/prover" - zkeyName = "blob_poseidon.zkey" -) +const zkeyName = "blob_poseidon.zkey" func TestZKProver_GenerateZKProofPerSample(t *testing.T) { proverPath, _ := filepath.Abs(prPath) From dd34a7cd47c2d8e20163788229031c3cebac7f08 Mon Sep 17 00:00:00 2001 From: syntrust Date: Mon, 15 Apr 2024 18:19:23 +0800 Subject: [PATCH 42/45] tidy --- go.mod | 1 - go.sum | 16 ---------------- 2 files changed, 17 deletions(-) diff --git a/go.mod b/go.mod index d2d62cd8..bb1eefc4 100644 --- a/go.mod +++ b/go.mod @@ -58,7 +58,6 @@ require ( github.com/hashicorp/golang-lru/arc/v2 v2.0.5 // indirect github.com/herumi/bls-eth-go-binary v1.28.1 // indirect github.com/huin/goupnp v1.3.0 // indirect - github.com/iden3/wasmer-go v0.0.1 // indirect github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/kilic/bls12-381 v0.1.1-0.20220929213557-ca162e8a70f4 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect diff --git a/go.sum b/go.sum index 4d12257b..ddaa7589 100644 --- a/go.sum +++ b/go.sum @@ -88,7 +88,6 @@ github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593 h1:aPEJyR4rPBvD github.com/cockroachdb/pebble v0.0.0-20230928194634-aa077af62593/go.mod h1:6hk1eMY/u5t+Cf18q5lFMUA1Rc+Sm5I6Ra1QuPyxXCo= github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= github.com/cockroachdb/redact v1.1.3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= -github.com/cockroachdb/sentry-go v0.6.1-cockroachdb.2/go.mod h1:8BT+cPK6xvFOcRlk0R8eg+OTkcqI6baNH4xAkpiYVvQ= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= @@ -193,7 +192,6 @@ github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclK github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= @@ -311,20 +309,12 @@ github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:q github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/iden3/go-rapidsnark/prover v0.0.10 h1:NvOfRPpex/k646UsqOcUy7a7uVl17t4ok9kWvpQg4+k= github.com/iden3/go-rapidsnark/prover v0.0.10/go.mod h1:wgDsmKOGCuWGtgVtuW9ARWNguNr4NJAIyg2G7+uTax0= -github.com/iden3/go-rapidsnark/types v0.0.2 h1:CjJSrlbWchHzuMRdxSYrEh7n/akP+Z2PLNbwT5yBmQY= -github.com/iden3/go-rapidsnark/types v0.0.2/go.mod h1:ApgcaUxKIgSRA6fAeFxK7p+lgXXfG4oA2HN5DhFlfF4= github.com/iden3/go-rapidsnark/types v0.0.3 h1:f0s1Qdut1qHe1O67+m+xUVRBPwSXnq5j0xSrBi0jqM4= github.com/iden3/go-rapidsnark/types v0.0.3/go.mod h1:ApgcaUxKIgSRA6fAeFxK7p+lgXXfG4oA2HN5DhFlfF4= github.com/iden3/go-rapidsnark/witness/v2 v2.0.0 h1:mkY6VDfwKVJc83QGKmwVXY2LYepidPrFAxskrjr8UCs= github.com/iden3/go-rapidsnark/witness/v2 v2.0.0/go.mod h1:3JRjqUfW1hgI9hzLDO0v8z/DUkR0ZUehhYLlnIfRxnA= -github.com/iden3/go-rapidsnark/witness/wasmer v0.0.0-20230524142950-0986cf057d4e h1:lqrevdLsG1k8ieaxgUQccf3unf73m3zmkHJ3oIdld90= -github.com/iden3/go-rapidsnark/witness/wasmer v0.0.0-20230524142950-0986cf057d4e/go.mod h1:WUtPVKXrhfZHJXavwId2+8J/fKMHQ92N0MZDxt8sfEA= github.com/iden3/go-rapidsnark/witness/wazero v0.0.0-20230524142950-0986cf057d4e h1:WeiFCrpj5pLRtSA4Mg03yTrSZhHHqN/k5b6bwxd9/tY= github.com/iden3/go-rapidsnark/witness/wazero v0.0.0-20230524142950-0986cf057d4e/go.mod h1:UEBifEzw62T6VzIHJeHuUgeLg2U/J9ttf7hOwQEqnYk= -github.com/iden3/go-rapidsnark/witness/wazero v0.0.1 h1:NSLCXVNWMSn+ilTCNUtIqbu9BViiICasq4FrMNCAds4= -github.com/iden3/go-rapidsnark/witness/wazero v0.0.1/go.mod h1:UEBifEzw62T6VzIHJeHuUgeLg2U/J9ttf7hOwQEqnYk= -github.com/iden3/wasmer-go v0.0.1 h1:TZKh8Se8B/73PvWrcu+FTU9L1k5XYAmtFbioj7l0Uog= -github.com/iden3/wasmer-go v0.0.1/go.mod h1:ZnZBAO012M7o+Q1INXLRIxKQgEcH2FuwL0Iga8A4ufg= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -357,14 +347,11 @@ github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZl github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= github.com/kataras/golog v0.0.10/go.mod h1:yJ8YKCmyL+nWjERB90Qwn+bdyBZsaQwU3bTVFgkFIp8= github.com/kataras/iris/v12 v12.1.8/go.mod h1:LMYy4VlP67TQ3Zgriz8RE2h2kMZV2SgMYbq3UhfoFmE= @@ -482,7 +469,6 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= @@ -511,7 +497,6 @@ github.com/multiformats/go-multistream v0.5.0/go.mod h1:n6tMZiwiP2wUsR8DgfDWw1dy github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= @@ -645,7 +630,6 @@ github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= From bc244b3a99a1bd7d0f4f89e594e238b661729403 Mon Sep 17 00:00:00 2001 From: syntrust Date: Thu, 18 Apr 2024 12:16:27 +0800 Subject: [PATCH 43/45] fix comment --- ethstorage/prover/zk_prover.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethstorage/prover/zk_prover.go b/ethstorage/prover/zk_prover.go index 1d5ff7dc..884ddbed 100644 --- a/ethstorage/prover/zk_prover.go +++ b/ethstorage/prover/zk_prover.go @@ -129,7 +129,7 @@ func (p *ZKProver) prove(dir string, pubInputs []byte) ([]byte, string, error) { inputFile := filepath.Join(buildDir, inputName) err = os.WriteFile(inputFile, pubInputs, 0644) if err != nil { - fmt.Println("Unable to write file:", err) + p.lg.Error("Write input file failed", "error", err) return nil, "", err } libDir := filepath.Join(p.dir, SnarkLib) From d6860f1378a6de0a82ca64a0159da872eb3a93ab Mon Sep 17 00:00:00 2001 From: syntrust Date: Thu, 20 Jun 2024 14:54:50 +0800 Subject: [PATCH 44/45] fix build --- integration_tests/node_mine_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration_tests/node_mine_test.go b/integration_tests/node_mine_test.go index 7d3221b2..228507a6 100644 --- a/integration_tests/node_mine_test.go +++ b/integration_tests/node_mine_test.go @@ -73,7 +73,7 @@ func TestMining(t *testing.T) { resourcesCtx, close := context.WithCancel(context.Background()) feed := new(event.Feed) - l1api := miner.NewL1MiningAPI(pClient, lg) + l1api := miner.NewL1MiningAPI(pClient, nil, lg) pvr := prover.NewKZGPoseidonProver( miningConfig.ZKWorkingDir, miningConfig.ZKeyFileName, From 54a9716955520eb1cebe5d135cb6fde2f1d8163f Mon Sep 17 00:00:00 2001 From: syntrust Date: Tue, 25 Jun 2024 17:17:56 +0800 Subject: [PATCH 45/45] remove waiting slots --- ethstorage/miner/worker.go | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/ethstorage/miner/worker.go b/ethstorage/miner/worker.go index cfc8d2f6..f9ac9066 100644 --- a/ethstorage/miner/worker.go +++ b/ethstorage/miner/worker.go @@ -393,19 +393,6 @@ func (w *worker) resultLoop() { continue } w.lg.Info("Mining result loop get result", "shard", result.startShardId, "block", result.blockNumber, "nonce", result.nonce) - // check block number to avoid `blockNumber == block.number` in the contract, loop for 5 times in case of empty slots - for i := 0; i < 5; i++ { - latest, err := w.l1API.BlockNumber(context.Background()) - if err != nil { - w.lg.Warn("Failed to get L1 block number", "error", err.Error()) - continue - } - if latest > result.blockNumber.Uint64() { - break - } - w.lg.Info("Will wait a slot for the block number to increase") - time.Sleep(slot * time.Second) - } txHash, err := w.l1API.SubmitMinedResult( context.Background(), w.storageMgr.ContractAddress(),