From ce0fd89e0bfa365f1fb0eed0e486908385adea11 Mon Sep 17 00:00:00 2001 From: giulio Date: Mon, 13 May 2024 22:55:33 +0200 Subject: [PATCH] Update compatibility with gnark v0.10.0 --- CHANGELOG.md | 9 +++++ go.mod | 14 ++++---- go.sum | 25 ++++++-------- helper.go | 11 ++---- setup/setup.go | 55 ++++++++++++++++++++--------- testutils/main_test.go | 34 ++++++++++++++---- verifier/templateBLS12_381.go | 53 ++++++++++++---------------- verifier/templateBN254.go | 65 +++++++++++++++-------------------- 8 files changed, 143 insertions(+), 123 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dccc34a..057e596 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## v0.1.5 +*Date: 2024-05-13* + +### Changed +- **Updates to match changes in gnark v0.10.0** + - Changed verifiers to reflect gnark updating to new version of Plonk paper + - Changed internal functions to match new gnark-crypto API + + ## v0.1.4 *Date: 2024-05-05* diff --git a/go.mod b/go.mod index a620eae..648079f 100644 --- a/go.mod +++ b/go.mod @@ -1,11 +1,13 @@ module github.com/giuliop/algoplonk -go 1.22.0 +go 1.21.1 + +toolchain go1.21.10 require ( github.com/algorand/go-algorand-sdk/v2 v2.4.0 - github.com/consensys/gnark v0.9.1 - github.com/consensys/gnark-crypto v0.12.2-0.20231013160410-1f65e75b6dfb + github.com/consensys/gnark v0.10.0 + github.com/consensys/gnark-crypto v0.12.2-0.20240504013751-564b6f724c3b github.com/mdehoog/gnark-ptau v0.0.0-20240119193856-bb5fe9a06e49 ) @@ -15,20 +17,16 @@ require ( github.com/bits-and-blooms/bitset v1.13.0 // indirect github.com/blang/semver/v4 v4.0.0 // indirect github.com/consensys/bavard v0.1.13 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect github.com/fxamacker/cbor/v2 v2.5.0 // indirect github.com/google/go-querystring v1.0.0 // indirect github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.19 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rs/zerolog v1.30.0 // indirect - github.com/stretchr/testify v1.8.4 // indirect github.com/x448/float16 v0.8.4 // indirect - golang.org/x/crypto v0.12.0 // indirect + golang.org/x/crypto v0.17.0 // indirect golang.org/x/sync v0.3.0 // indirect golang.org/x/sys v0.16.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect rsc.io/tmplfunc v0.0.3 // indirect ) diff --git a/go.sum b/go.sum index 74406ae..7b79d8d 100644 --- a/go.sum +++ b/go.sum @@ -12,10 +12,10 @@ github.com/chrismcguire/gobberish v0.0.0-20150821175641-1d8adb509a0e h1:CHPYEbz7 github.com/chrismcguire/gobberish v0.0.0-20150821175641-1d8adb509a0e/go.mod h1:6Xhs0ZlsRjXLIiSMLKafbZxML/j30pg9Z1priLuha5s= github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= -github.com/consensys/gnark v0.9.1 h1:aTwBp5469MY/2jNrf4ABrqHRW3+JytfkADdw4ZBY7T0= -github.com/consensys/gnark v0.9.1/go.mod h1:udWvWGXnfBE7mn7BsNoGAvZDnUhcONBEtNijvVjfY80= -github.com/consensys/gnark-crypto v0.12.2-0.20231013160410-1f65e75b6dfb h1:f0BMgIjhZy4lSRHCXFbQst85f5agZAjtDMixQqBWNpc= -github.com/consensys/gnark-crypto v0.12.2-0.20231013160410-1f65e75b6dfb/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= +github.com/consensys/gnark v0.10.0 h1:yhi6ThoeFP7WrH8zQDaO56WVXe9iJEBSkfrZ9PZxabw= +github.com/consensys/gnark v0.10.0/go.mod h1:VJU5JrrhZorbfDH+EUjcuFWr2c5z19tHPh8D6KVQksU= +github.com/consensys/gnark-crypto v0.12.2-0.20240504013751-564b6f724c3b h1:tu0NaVr64o6vXzy9rYSK/LCZXmS+u/k9eP1F8OtRUWQ= +github.com/consensys/gnark-crypto v0.12.2-0.20240504013751-564b6f724c3b/go.mod h1:wKqwsieaKPThcFkHe0d0zMsbHEUWFmZcG7KBCse210o= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -29,10 +29,10 @@ github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b h1:h9U78+dx9a4BKdQkBBos92HalKpaGKHrp+3Uo6yTodo= github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/ingonyama-zk/icicle v0.0.0-20230928131117-97f0079e5c71 h1:YxI1RTPzpFJ3MBmxPl3Bo0F7ume7CmQEC1M9jL6CT94= +github.com/ingonyama-zk/icicle v0.0.0-20230928131117-97f0079e5c71/go.mod h1:kAK8/EoN7fUEmakzgZIYdWy1a2rBnpCaZLqSHwZWxEk= +github.com/ingonyama-zk/iciclegnark v0.1.0 h1:88MkEghzjQBMjrYRJFxZ9oR9CTIpB8NG2zLeCJSvXKQ= +github.com/ingonyama-zk/iciclegnark v0.1.0/go.mod h1:wz6+IpyHKs6UhMMoQpNqz1VY+ddfKqC/gRwR/64W6WU= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= @@ -50,8 +50,6 @@ github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFV github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= -github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.30.0 h1:SymVODrcRsaRaSInD9yQtKbtWqwsfoPcRff/oRXLj4c= github.com/rs/zerolog v1.30.0/go.mod h1:/tk+P47gFdPXq4QYjvCmT5/Gsug2nagsFWBWhAiSi1w= @@ -62,8 +60,8 @@ github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcY github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk= -golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= +golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= +golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= @@ -94,9 +92,6 @@ golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/helper.go b/helper.go index cc6eeaf..55bde7f 100644 --- a/helper.go +++ b/helper.go @@ -50,7 +50,7 @@ func marshalPlonkBls12381Proof(proof *plonk_bls12381.Proof) []byte { // [32]byte o_at_zeta; // [32]byte s1_at_zeta; // [32]byte s2_at_zeta; - for i := 2; i < 7; i++ { + for i := 1; i < 6; i++ { tmp32 = proof.BatchedProof.ClaimedValues[i].Bytes() res = append(res, tmp32[:]...) } @@ -63,13 +63,6 @@ func marshalPlonkBls12381Proof(proof *plonk_bls12381.Proof) []byte { tmp32 = proof.ZShiftedOpening.ClaimedValue.Bytes() res = append(res, tmp32[:]...) - // [32]byte quotient_polynomial_at_zeta; - // [32]byte linearization_polynomial_at_zeta; - tmp32 = proof.BatchedProof.ClaimedValues[0].Bytes() - res = append(res, tmp32[:]...) - tmp32 = proof.BatchedProof.ClaimedValues[1].Bytes() - res = append(res, tmp32[:]...) - // [3][32]byte opening_at_zeta_proof tmp96 = proof.BatchedProof.H.RawBytes() res = append(res, tmp96[:]...) @@ -82,7 +75,7 @@ func marshalPlonkBls12381Proof(proof *plonk_bls12381.Proof) []byte { // [][96]byte wire_committed_commitments; if len(proof.Bsb22Commitments) > 0 { for i := 0; i < len(proof.Bsb22Commitments); i++ { - tmp32 = proof.BatchedProof.ClaimedValues[7+i].Bytes() + tmp32 = proof.BatchedProof.ClaimedValues[6+i].Bytes() res = append(res, tmp32[:]...) } for _, bc := range proof.Bsb22Commitments { diff --git a/setup/setup.go b/setup/setup.go index 7be7091..2b77977 100644 --- a/setup/setup.go +++ b/setup/setup.go @@ -5,7 +5,6 @@ import ( "embed" "encoding/binary" "fmt" - "math/big" "github.com/consensys/gnark-crypto/ecc" bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" @@ -15,6 +14,7 @@ import ( "github.com/consensys/gnark-crypto/kzg" "github.com/consensys/gnark/backend/plonk" "github.com/consensys/gnark/constraint" + "github.com/consensys/gnark/test/unsafekzg" ) // Conf specified what setup to run, either trusted as per doc.go or a test only @@ -31,34 +31,55 @@ const ( func Run(ccs constraint.ConstraintSystem, curve ecc.ID, setup Conf) ( plonk.ProvingKey, plonk.VerifyingKey, error) { + if setup == TestOnly { + srs, lagrangeSrs, err := unsafekzg.NewSRS(ccs) + if err != nil { + return nil, nil, fmt.Errorf("error creating test SRS: %v", err) + } + return plonk.Setup(ccs, srs, lagrangeSrs) + } + + // setup == Trusted + var srs, lagrangeSrs kzg.SRS + numGates := uint64(ccs.GetNbConstraints() + ccs.GetNbPublicVariables()) numGates = ecc.NextPowerOfTwo(numGates) + 3 - var srs kzg.SRS - var err error - switch curve { case ecc.BLS12_381: - if setup == Trusted { - srs, err = trustedSetupBLS12381(numGates) - } else if setup == TestOnly { - srs, err = kzg_bls12381.NewSRS(numGates, big.NewInt(-1)) + _srs, err := trustedSetupBLS12381(numGates) + if err != nil { + return nil, nil, fmt.Errorf("error creating SRS: %v", err) + } + srs = _srs + _lagrangeSrs := &kzg_bls12381.SRS{Vk: _srs.Vk} + lagrangeG1, err := kzg_bls12381.ToLagrangeG1( + _srs.Pk.G1[:len(_srs.Pk.G1)-3]) + if err != nil { + return nil, nil, fmt.Errorf("error creating lagrange G1: %v", err) } + _lagrangeSrs.Pk.G1 = lagrangeG1 + lagrangeSrs = _lagrangeSrs + case ecc.BN254: - if setup == Trusted { - srs, err = trustedSetupBN254(numGates) - } else if setup == TestOnly { - srs, err = kzg_bn254.NewSRS(numGates, big.NewInt(-1)) + _srs, err := trustedSetupBN254(numGates) + if err != nil { + return nil, nil, fmt.Errorf("error creating SRS: %v", err) + } + srs = _srs + _lagrangeSrs := &kzg_bn254.SRS{Vk: _srs.Vk} + lagrangeG1, err := kzg_bn254.ToLagrangeG1(_srs.Pk.G1[:len(_srs.Pk.G1)-3]) + if err != nil { + return nil, nil, fmt.Errorf("error creating lagrange G1: %v", err) } + _lagrangeSrs.Pk.G1 = lagrangeG1 + lagrangeSrs = _lagrangeSrs + default: return nil, nil, fmt.Errorf("unsupported curve: %v", curve) } - if err != nil { - return nil, nil, fmt.Errorf("error creating SRS: %v", err) - } - - return plonk.Setup(ccs, srs) + return plonk.Setup(ccs, srs, lagrangeSrs) } //go:embed bls12_381/pk.bin bls12_381/vk.bin bn254/pk.bin bn254/vk.bin diff --git a/testutils/main_test.go b/testutils/main_test.go index 2061d62..a5a5703 100644 --- a/testutils/main_test.go +++ b/testutils/main_test.go @@ -5,6 +5,7 @@ import ( "hash" "math/big" "path/filepath" + "strings" "testing" "github.com/algorand/go-algorand-sdk/v2/types" @@ -144,13 +145,18 @@ func TestCircuitBothCurves(t *testing.T) { t.Fatalf("error calling verifier app: %v", err) } - rawValue := result.RawReturnValue - if len(rawValue) == 0 { - t.Fatalf("verifier app returned empty value") + //printDebugLogs(result.TransactionInfo.Logs) + + if result.DecodeError != nil { + t.Fatalf("error decoding result: %v", result.DecodeError) } - if rawValue[0] != 0x80 { - t.Fatalf("Verifier app did not return true, but: %v\n", - result.ReturnValue) + switch result.ReturnValue { + case true: + return + case false: + t.Fatal("verifier app returned false") + default: + t.Fatal("verifier app failed") } } } @@ -247,3 +253,19 @@ func buildZeroHashes(levels int, hash HashFunc) [][]byte { } return zeroHashes } + +// printDebugLogs prints debuglogs from a transaction as byte slices. +// If the logs are in the format of ... -> .., it will print the left part as +// a string and the right part as a byte slice. +func printDebugLogs(logs [][]byte) { + for _, bytes := range logs { + str := string(bytes) + parts := strings.Split(str, " -> ") + if len(parts) > 1 { + leftPart := strings.TrimSpace(parts[0]) + fmt.Printf("%s -> ", leftPart) + bytes = []byte(parts[1]) + } + fmt.Printf("%v\n", bytes) + } +} diff --git a/verifier/templateBLS12_381.go b/verifier/templateBLS12_381.go index 101a48e..e5b0793 100644 --- a/verifier/templateBLS12_381.go +++ b/verifier/templateBLS12_381.go @@ -7,11 +7,10 @@ import typing import algopy as py from algopy import subroutine, BigUInt, Bytes, arc4, UInt64, urange from algopy.arc4 import UInt256, abimethod, DynamicArray, StaticArray, String -from algopy.op import sha256, EllipticCurve as ec, EC, bzero, setbit_bytes +from algopy.op import bzero, sha256, EllipticCurve as ec, EC, setbit_bytes Bytes32: typing.TypeAlias = StaticArray[arc4.Byte, typing.Literal[32]] - #################### Curve parameters ################# # curve order @@ -64,7 +63,7 @@ class {{ (contractName) }}(py.ARC4Contract): q = BigUInt(R_MOD) # check proof and public inputs lengths - assert proof.length == 35 + assert proof.length == 33 assert public_inputs.length == {{ .NbPublicVariables }} ### Read verifying key ### @@ -116,12 +115,10 @@ class {{ (contractName) }}(py.ARC4Contract): # z(x) GRAND_PRODUCT = proof[23].bytes + proof[24].bytes + proof[25].bytes GRAND_PRODUCT_AT_Z_OMEGA = proof[26].copy() # z(w*zeta) - QUOTIENT_POLY_AT_Z = proof[27].copy() # t(zeta) - LINEAR_POLY_AT_Z = proof[28].copy() # r(zeta) - # Folded proof for opening of H, linear poly, l, r, o, s1, s2, qc - BATCH_OPENING_AT_Z = proof[29].bytes + proof[30].bytes + proof[31].bytes - OPENING_AT_Z_OMEGA = proof[32].bytes + proof[33].bytes + proof[34].bytes + # Folded proof for opening of linear poly, l, r, o, s1, s2 + BATCH_OPENING_AT_Z = proof[27].bytes + proof[28].bytes + proof[29].bytes + OPENING_AT_Z_OMEGA = proof[30].bytes + proof[31].bytes + proof[32].bytes ### check proof public inputs are well-formed ### if (BigUInt.from_bytes(L_AT_Z.bytes) >= q @@ -130,8 +127,7 @@ class {{ (contractName) }}(py.ARC4Contract): or BigUInt.from_bytes(S1_AT_Z.bytes) >= q or BigUInt.from_bytes(S2_AT_Z.bytes) >= q or BigUInt.from_bytes(GRAND_PRODUCT_AT_Z_OMEGA.bytes) >= q - or BigUInt.from_bytes(QUOTIENT_POLY_AT_Z.bytes) >= q - or BigUInt.from_bytes(LINEAR_POLY_AT_Z.bytes) >= q): + ): {{/*}}py.log("error: invalid proof"){{*/ -}} return arc4.Bool(False) @@ -215,7 +211,7 @@ class {{ (contractName) }}(py.ARC4Contract): res = (res * alpha) % q alpha2Lagrange = res - # verify quotient polynomial evaluation at zeta + # verify opening linearization polynomial s1 = (BigUInt.from_bytes(S1_AT_Z.bytes) * beta) % q s1 = (s1 + gamma + BigUInt.from_bytes(L_AT_Z.bytes)) % q @@ -229,14 +225,8 @@ class {{ (contractName) }}(py.ARC4Contract): s1 = (s1 * alpha) % q s1 = (s1 * BigUInt.from_bytes(GRAND_PRODUCT_AT_Z_OMEGA.bytes)) % q - quot = (BigUInt.from_bytes(LINEAR_POLY_AT_Z.bytes) + PI + s1 + q - - alpha2Lagrange) % q - - s2 = (BigUInt.from_bytes(QUOTIENT_POLY_AT_Z.bytes) * Zz) % q - - if quot != s2: - {{/*}}py.log("error: quotient polynomial evaluation verification failed"){{*/ -}} - return arc4.Bool(False) + s1 = (s1 + PI + q - alpha2Lagrange) % q + linearized_poly_at_z = (q - s1) # compute the folded commitment to H n2 = VK_DOMAIN_SIZE + BigUInt(2) @@ -245,6 +235,9 @@ class {{ (contractName) }}(py.ARC4Contract): folded_h = ec.add(EC.BLS12_381g1, folded_h, H1) folded_h = ec.scalar_mul(EC.BLS12_381g1, folded_h, zn2.bytes) folded_h = ec.add(EC.BLS12_381g1, folded_h, H0) + znminus1 = (expmod(zeta, VK_DOMAIN_SIZE, q) + q - BigUInt(1)) % q + folded_h = ec.scalar_mul(EC.BLS12_381g1, folded_h, znminus1.bytes) + folded_h = invert(folded_h) # compute commitment to linearization polynomial u = (BigUInt.from_bytes(GRAND_PRODUCT_AT_Z_OMEGA.bytes) * beta) % q @@ -290,24 +283,22 @@ class {{ (contractName) }}(py.ARC4Contract): add_term = ec.scalar_mul(EC.BLS12_381g1, GRAND_PRODUCT, s2.bytes) lin_poly_com = ec.add(EC.BLS12_381g1, lin_poly_com, add_term) + lin_poly_com = ec.add(EC.BLS12_381g1, lin_poly_com, folded_h) + # generate challenge to fold the opening proofs - r_pre = sha256(b'gamma' + UInt256(zeta).bytes + folded_h + lin_poly_com - + fs(L_COM) + fs(R_COM) + fs(O_COM) + VK_S1_fs + VK_S2_fs + QUOTIENT_POLY_AT_Z.bytes - + LINEAR_POLY_AT_Z.bytes + L_AT_Z.bytes + R_AT_Z.bytes + linearized_poly_at_z_bytes = bzero(32) | linearized_poly_at_z.bytes + r_pre = sha256(b'gamma' + UInt256(zeta).bytes + lin_poly_com + + fs(L_COM) + fs(R_COM) + fs(O_COM) + VK_S1_fs + VK_S2_fs + + linearized_poly_at_z_bytes + L_AT_Z.bytes + R_AT_Z.bytes + O_AT_Z.bytes + S1_AT_Z.bytes + S2_AT_Z.bytes + GRAND_PRODUCT_AT_Z_OMEGA.bytes) r = curvemod(r_pre) r_acc = r # fold the proof in one point - digest = folded_h - add_term = ec.scalar_mul(EC.BLS12_381g1, lin_poly_com, r_acc.bytes) - digest = ec.add(EC.BLS12_381g1, digest, add_term) - claims = (BigUInt.from_bytes(QUOTIENT_POLY_AT_Z.bytes) - + (BigUInt.from_bytes(LINEAR_POLY_AT_Z.bytes) * r_acc) - ) % q + digest = lin_poly_com + claims = linearized_poly_at_z - r_acc = (r_acc * r) % q add_term = ec.scalar_mul(EC.BLS12_381g1, L_COM, r_acc.bytes) digest = ec.add(EC.BLS12_381g1, digest, add_term) claims = (claims + (BigUInt.from_bytes(L_AT_Z.bytes) * r_acc)) % q @@ -373,9 +364,9 @@ class {{ (contractName) }}(py.ARC4Contract): py.log(b"zeta -> " + zeta.bytes) py.log(b"PI -> " + PI.bytes) py.log(b"alpha2Lagrange -> " + alpha2Lagrange.bytes) - py.log(b"folded_h -> " + folded_h) + py.log(b"linearized_poly_at_z -> " + linearized_poly_at_z_bytes) py.log(b"lin_poly_com -> " + lin_poly_com) - py.log(b"gamma -> " + gamma.bytes) + py.log(b"r -> " + r.bytes) py.log(b'digest -> ' + digest) py.log(b'claims -> ' + claims.bytes) {{ */ -}} diff --git a/verifier/templateBN254.go b/verifier/templateBN254.go index 7ea6e09..6b209c9 100644 --- a/verifier/templateBN254.go +++ b/verifier/templateBN254.go @@ -6,8 +6,8 @@ import typing import algopy as py from algopy import subroutine, BigUInt, Bytes, arc4, UInt64, urange -from algopy.arc4 import UInt256, abimethod, Tuple, DynamicArray, StaticArray, String -from algopy.op import sha256, EllipticCurve as ec, EC +from algopy.arc4 import UInt256, abimethod, DynamicArray, StaticArray, String +from algopy.op import bzero, sha256, EllipticCurve as ec, EC Bytes32: typing.TypeAlias = StaticArray[arc4.Byte, typing.Literal[32]] @@ -62,7 +62,7 @@ class {{ (contractName) }}(py.ARC4Contract): q = BigUInt(R_MOD) # check proof and public inputs lengths - assert proof.length == 26 + assert proof.length == 24 assert public_inputs.length == {{ .NbPublicVariables }} # Read verifying key @@ -102,12 +102,10 @@ class {{ (contractName) }}(py.ARC4Contract): S2_AT_Z = proof[16].copy() # s2(zeta) GRAND_PRODUCT = proof[17].bytes + proof[18].bytes # z(x) GRAND_PRODUCT_AT_Z_OMEGA = proof[19].copy() # z(w*zeta) - QUOTIENT_POLY_AT_Z = proof[20].copy() # t(zeta) - LINEAR_POLY_AT_Z = proof[21].copy() # r(zeta) - # Folded proof for opening of H, linear poly, l, r, o, s1, s2, qc - BATCH_OPENING_AT_Z = proof[22].bytes + proof[23].bytes - OPENING_AT_Z_OMEGA = proof[24].bytes + proof[25].bytes + # Folded proof for opening of linear poly, l, r, o, s1, s2 + BATCH_OPENING_AT_Z = proof[20].bytes + proof[21].bytes + OPENING_AT_Z_OMEGA = proof[22].bytes + proof[23].bytes ### check proof public inputs are well-formed ### if (BigUInt.from_bytes(L_AT_Z.bytes) >= q @@ -116,8 +114,7 @@ class {{ (contractName) }}(py.ARC4Contract): or BigUInt.from_bytes(S1_AT_Z.bytes) >= q or BigUInt.from_bytes(S2_AT_Z.bytes) >= q or BigUInt.from_bytes(GRAND_PRODUCT_AT_Z_OMEGA.bytes) >= q - or BigUInt.from_bytes(QUOTIENT_POLY_AT_Z.bytes) >= q - or BigUInt.from_bytes(LINEAR_POLY_AT_Z.bytes) >= q): + ): {{/*}}py.log("error: invalid proof"){{*/ -}} return arc4.Bool(False) @@ -135,8 +132,8 @@ class {{ (contractName) }}(py.ARC4Contract): for i in urange(public_inputs.length): public_inputs_bytes += public_inputs[i].bytes - gamma_pre = sha256(b'gamma' + VK_S1 + VK_S2 + VK_S3 + VK_QL + VK_QR + VK_QM + VK_QO + VK_QK - + public_inputs_bytes + L_COM + R_COM + O_COM) + gamma_pre = sha256(b'gamma' + VK_S1 + VK_S2 + VK_S3 + VK_QL + VK_QR + + VK_QM + VK_QO + VK_QK + public_inputs_bytes + L_COM + R_COM + O_COM) beta_pre = sha256(b'beta' + gamma_pre) alpha_pre = sha256(b'alpha' + beta_pre + GRAND_PRODUCT) zeta_pre = sha256(b'zeta' + alpha_pre + H_0 + H_1 + H_2) @@ -200,7 +197,7 @@ class {{ (contractName) }}(py.ARC4Contract): res = (res * alpha) % q alpha2Lagrange = res - # verify quotient polynomial evaluation at zeta + # verify opening linearization polynomial s1 = (BigUInt.from_bytes(S1_AT_Z.bytes) * beta) % q s1 = (s1 + gamma + BigUInt.from_bytes(L_AT_Z.bytes)) % q @@ -214,14 +211,8 @@ class {{ (contractName) }}(py.ARC4Contract): s1 = (s1 * alpha) % q s1 = (s1 * BigUInt.from_bytes(GRAND_PRODUCT_AT_Z_OMEGA.bytes)) % q - quot = (BigUInt.from_bytes(LINEAR_POLY_AT_Z.bytes) + PI + s1 + q - - alpha2Lagrange) % q - - s2 = (BigUInt.from_bytes(QUOTIENT_POLY_AT_Z.bytes) * Zz) % q - - if quot != s2: - {{/*}}py.log("error: quotient polynomial evaluation verification failed"){{*/ -}} - return arc4.Bool(False) + s1 = (s1 + PI + q - alpha2Lagrange) % q + linearized_poly_at_z = (q - s1) # compute the folded commitment to H n2 = VK_DOMAIN_SIZE + BigUInt(2) @@ -230,6 +221,9 @@ class {{ (contractName) }}(py.ARC4Contract): folded_h = ec.add(EC.BN254g1, folded_h, H_1) folded_h = ec.scalar_mul(EC.BN254g1, folded_h, zn2.bytes) folded_h = ec.add(EC.BN254g1, folded_h, H_0) + znminus1 = (expmod(zeta, VK_DOMAIN_SIZE, q) + q - BigUInt(1)) % q + folded_h = ec.scalar_mul(EC.BN254g1, folded_h, znminus1.bytes) + folded_h = invert(folded_h) # compute commitment to linearization polynomial u = (BigUInt.from_bytes(GRAND_PRODUCT_AT_Z_OMEGA.bytes) * beta) % q @@ -275,24 +269,21 @@ class {{ (contractName) }}(py.ARC4Contract): add_term = ec.scalar_mul(EC.BN254g1, GRAND_PRODUCT, s2.bytes) lin_poly_com = ec.add(EC.BN254g1, lin_poly_com, add_term) + lin_poly_com = ec.add(EC.BN254g1, lin_poly_com, folded_h) + # generate challenge to fold the opening proofs - r_pre = sha256(b'gamma' + UInt256(zeta).bytes + folded_h + lin_poly_com - + L_COM + R_COM + O_COM + VK_S1 + VK_S2 + QUOTIENT_POLY_AT_Z.bytes - + LINEAR_POLY_AT_Z.bytes + L_AT_Z.bytes + R_AT_Z.bytes - + O_AT_Z.bytes + S1_AT_Z.bytes + S2_AT_Z.bytes - + GRAND_PRODUCT_AT_Z_OMEGA.bytes) + linearized_poly_at_z_bytes = bzero(32) | linearized_poly_at_z.bytes + r_pre = sha256(b'gamma' + UInt256(zeta).bytes + lin_poly_com + + L_COM + R_COM + O_COM + VK_S1 + VK_S2 + linearized_poly_at_z_bytes + + L_AT_Z.bytes + R_AT_Z.bytes + O_AT_Z.bytes + S1_AT_Z.bytes + + S2_AT_Z.bytes + GRAND_PRODUCT_AT_Z_OMEGA.bytes) r = curvemod(r_pre) r_acc = r # fold the proof in one point - digest = folded_h - add_term = ec.scalar_mul(EC.BN254g1, lin_poly_com, r_acc.bytes) - digest = ec.add(EC.BN254g1, digest, add_term) - claims = (BigUInt.from_bytes(QUOTIENT_POLY_AT_Z.bytes) - + (BigUInt.from_bytes(LINEAR_POLY_AT_Z.bytes) * r_acc) - ) % q + digest = lin_poly_com + claims = linearized_poly_at_z - r_acc = (r_acc * r) % q add_term = ec.scalar_mul(EC.BN254g1, L_COM, r_acc.bytes) digest = ec.add(EC.BN254g1, digest, add_term) claims = (claims + (BigUInt.from_bytes(L_AT_Z.bytes) * r_acc)) % q @@ -350,19 +341,19 @@ class {{ (contractName) }}(py.ARC4Contract): + UInt256(G2_SRS_1_X_1).bytes + UInt256(G2_SRS_1_X_0).bytes + UInt256(G2_SRS_1_Y_1).bytes + UInt256(G2_SRS_1_Y_0).bytes) - {{/* -}} + {{/*}} py.log(b"gamma -> " + gamma.bytes) py.log(b"beta -> " + beta.bytes) py.log(b"alpha -> " + alpha.bytes) py.log(b"zeta -> " + zeta.bytes) py.log(b"PI -> " + PI.bytes) py.log(b"alpha2Lagrange -> " + alpha2Lagrange.bytes) - py.log(b"folded_h -> " + folded_h) + py.log(b"linearized_poly_at_z -> " + linearized_poly_at_z_bytes) py.log(b"lin_poly_com -> " + lin_poly_com) - py.log(b"gamma -> " + gamma.bytes) + py.log(b"r -> " + r.bytes) py.log(b'digest -> ' + digest) py.log(b'claims -> ' + claims.bytes) - {{ */ -}} + {{*/}} check = ec.pairing_check(EC.BN254g1, digest + quotient, g2) return arc4.Bool(check)