diff --git a/backend/groth16/bn254/mpcsetup/marshal.go b/backend/groth16/bn254/mpcsetup/marshal.go index 08cb2ae3d1..a187342e7f 100644 --- a/backend/groth16/bn254/mpcsetup/marshal.go +++ b/backend/groth16/bn254/mpcsetup/marshal.go @@ -17,8 +17,9 @@ package mpcsetup import ( - curve "github.com/consensys/gnark-crypto/ecc/bn254" "io" + + curve "github.com/consensys/gnark-crypto/ecc/bn254" ) // WriteTo implements io.WriterTo @@ -108,6 +109,7 @@ func (c *Phase2) writeTo(writer io.Writer) (int64, error) { c.Parameters.G1.L, c.Parameters.G1.Z, &c.Parameters.G2.Delta, + &c.Parameters.G2.GRootSigmaNeg, } for _, v := range toEncode { @@ -116,6 +118,13 @@ func (c *Phase2) writeTo(writer io.Writer) (int64, error) { } } + enc.Encode(uint64(len(c.Parameters.G1.BasisExpSigma))) + for _, h := range c.Parameters.G1.BasisExpSigma { + if err := enc.Encode(h); err != nil { + return enc.BytesWritten(), err + } + } + return enc.BytesWritten(), nil } @@ -130,6 +139,7 @@ func (c *Phase2) ReadFrom(reader io.Reader) (int64, error) { &c.Parameters.G1.L, &c.Parameters.G1.Z, &c.Parameters.G2.Delta, + &c.Parameters.G2.GRootSigmaNeg, } for _, v := range toEncode { @@ -138,10 +148,21 @@ func (c *Phase2) ReadFrom(reader io.Reader) (int64, error) { } } + var basisExpSigmanLen uint64 + if err := dec.Decode(&basisExpSigmanLen); err != nil { + return dec.BytesRead(), err + } + + c.Parameters.G1.BasisExpSigma = make([][]curve.G1Affine, basisExpSigmanLen) + for i := 0; i < int(basisExpSigmanLen); i++ { + if err := dec.Decode(&c.Parameters.G1.BasisExpSigma[i]); err != nil { + return dec.BytesRead(), err + } + } + c.Hash = make([]byte, 32) n, err := reader.Read(c.Hash) return int64(n) + dec.BytesRead(), err - } // WriteTo implements io.WriterTo @@ -150,6 +171,7 @@ func (c *Phase2Evaluations) WriteTo(writer io.Writer) (int64, error) { toEncode := []interface{}{ c.G1.A, c.G1.B, + c.G1.VKK, c.G2.B, } @@ -159,6 +181,13 @@ func (c *Phase2Evaluations) WriteTo(writer io.Writer) (int64, error) { } } + enc.Encode(uint64(len(c.G1.Basis))) + for _, h := range c.G1.Basis { + if err := enc.Encode(h); err != nil { + return enc.BytesWritten(), err + } + } + return enc.BytesWritten(), nil } @@ -168,6 +197,7 @@ func (c *Phase2Evaluations) ReadFrom(reader io.Reader) (int64, error) { toEncode := []interface{}{ &c.G1.A, &c.G1.B, + &c.G1.VKK, &c.G2.B, } @@ -177,5 +207,17 @@ func (c *Phase2Evaluations) ReadFrom(reader io.Reader) (int64, error) { } } + var basisLen uint64 + if err := dec.Decode(&basisLen); err != nil { + return dec.BytesRead(), err + } + + c.G1.Basis = make([][]curve.G1Affine, basisLen) + for i := 0; i < int(basisLen); i++ { + if err := dec.Decode(&c.G1.Basis[i]); err != nil { + return dec.BytesRead(), err + } + } + return dec.BytesRead(), nil } diff --git a/backend/groth16/bn254/mpcsetup/phase2.go b/backend/groth16/bn254/mpcsetup/phase2.go index 3fcafb30da..50eefc533c 100644 --- a/backend/groth16/bn254/mpcsetup/phase2.go +++ b/backend/groth16/bn254/mpcsetup/phase2.go @@ -23,6 +23,8 @@ import ( curve "github.com/consensys/gnark-crypto/ecc/bn254" "github.com/consensys/gnark-crypto/ecc/bn254/fr" + + utils "github.com/consensys/gnark/backend/groth16/internal" "github.com/consensys/gnark/constraint" cs "github.com/consensys/gnark/constraint/bn254" ) @@ -30,6 +32,7 @@ import ( type Phase2Evaluations struct { G1 struct { A, B, VKK []curve.G1Affine + Basis [][]curve.G1Affine } G2 struct { B []curve.G2Affine @@ -39,11 +42,12 @@ type Phase2Evaluations struct { type Phase2 struct { Parameters struct { G1 struct { - Delta curve.G1Affine - L, Z []curve.G1Affine + Delta curve.G1Affine + L, Z []curve.G1Affine + BasisExpSigma [][]curve.G1Affine } G2 struct { - Delta curve.G2Affine + Delta, GRootSigmaNeg curve.G2Affine } } PublicKey PublicKey @@ -105,15 +109,26 @@ func InitPhase2(r1cs *cs.R1CS, srs1 *Phase1) (Phase2, Phase2Evaluations) { coeffAlphaTau1 := lagrangeCoeffsG1(srs.G1.AlphaTau, size) coeffBetaTau1 := lagrangeCoeffsG1(srs.G1.BetaTau, size) - internal, secret, public := r1cs.GetNbVariables() - nWires := internal + secret + public + // a commitment is itself defined by a hint so the prover considers it private + // but the verifier will need to inject the value itself so on the groth16 + // level it must be considered public + nbWires := r1cs.NbInternalVariables + r1cs.GetNbPublicVariables() + r1cs.GetNbSecretVariables() + commitmentInfo := r1cs.CommitmentInfo.(constraint.Groth16Commitments) + commitmentWires := commitmentInfo.CommitmentIndexes() + privateCommitted := commitmentInfo.GetPrivateCommitted() + nbPrivateCommittedWires := utils.NbElements(privateCommitted) + + nbPublicWires := r1cs.GetNbPublicVariables() + len(commitmentInfo) + nbPrivateWires := r1cs.GetNbSecretVariables() + r1cs.NbInternalVariables - nbPrivateCommittedWires - len(commitmentInfo) + var evals Phase2Evaluations - evals.G1.A = make([]curve.G1Affine, nWires) - evals.G1.B = make([]curve.G1Affine, nWires) - evals.G2.B = make([]curve.G2Affine, nWires) - bA := make([]curve.G1Affine, nWires) - aB := make([]curve.G1Affine, nWires) - C := make([]curve.G1Affine, nWires) + evals.G1.A = make([]curve.G1Affine, nbWires) + evals.G1.B = make([]curve.G1Affine, nbWires) + evals.G1.Basis = make([][]curve.G1Affine, nbPrivateCommittedWires) + evals.G2.B = make([]curve.G2Affine, nbWires) + bA := make([]curve.G1Affine, nbWires) + aB := make([]curve.G1Affine, nbWires) + C := make([]curve.G1Affine, nbWires) // TODO @gbotrel use constraint iterator when available. @@ -153,21 +168,56 @@ func InitPhase2(r1cs *cs.R1CS, srs1 *Phase1) (Phase2, Phase2Evaluations) { bitReverse(c2.Parameters.G1.Z) c2.Parameters.G1.Z = c2.Parameters.G1.Z[:n-1] - // Evaluate L - nPrivate := internal + secret - c2.Parameters.G1.L = make([]curve.G1Affine, nPrivate) - evals.G1.VKK = make([]curve.G1Affine, public) - offset := public - for i := 0; i < nWires; i++ { + c2.Parameters.G1.L = make([]curve.G1Affine, nbPrivateWires) + evals.G1.VKK = make([]curve.G1Affine, nbPublicWires) + evals.G1.Basis = make([][]curve.G1Affine, len(commitmentInfo)) + for i := range commitmentInfo { + evals.G1.Basis[i] = make([]curve.G1Affine, len(privateCommitted[i])) + } + + vI := 0 // number of public wires seen so far + cI := make([]int, len(commitmentInfo)) // number of private committed wires seen so far for each commitment + nbPrivateCommittedSeen := 0 // = ∑ᵢ cI[i] + nbCommitmentsSeen := 0 + + for i := range bA { var tmp curve.G1Affine tmp.Add(&bA[i], &aB[i]) tmp.Add(&tmp, &C[i]) - if i < public { - evals.G1.VKK[i].Set(&tmp) + commitment := -1 // index of the commitment that commits to this variable as a private or commitment value + var isCommitment, isPublic bool + if isPublic = i < r1cs.GetNbPublicVariables(); !isPublic { + if nbCommitmentsSeen < len(commitmentWires) && commitmentWires[nbCommitmentsSeen] == i { + isCommitment = true + nbCommitmentsSeen++ + } + + for j := range commitmentInfo { // does commitment j commit to i? + if cI[j] < len(privateCommitted[j]) && privateCommitted[j][cI[j]] == i { + commitment = j + break // frontend guarantees that no private variable is committed to more than once + } + } + } + + if isPublic || commitment != -1 || isCommitment { + if isPublic || isCommitment { + evals.G1.VKK[vI] = tmp + vI++ + } else { // committed and private + evals.G1.Basis[commitment][cI[commitment]] = tmp + cI[commitment]++ + nbPrivateCommittedSeen++ + } } else { - c2.Parameters.G1.L[i-offset].Set(&tmp) + c2.Parameters.G1.L[i-vI-nbPrivateCommittedSeen] = tmp // vI = nbPublicSeen + nbCommitmentsSeen } } + + basisExpSigma, gRootSigmaNeg := InitPedersen(evals.G1.Basis...) + c2.Parameters.G1.BasisExpSigma = basisExpSigma + c2.Parameters.G2.GRootSigmaNeg = gRootSigmaNeg + // Set δ public key var delta fr.Element delta.SetOne() @@ -195,6 +245,20 @@ func (c *Phase2) Contribute() { c.Parameters.G1.Delta.ScalarMultiplication(&c.Parameters.G1.Delta, &deltaBI) c.Parameters.G2.Delta.ScalarMultiplication(&c.Parameters.G2.Delta, &deltaBI) + // Update GRootSigmaNeg using δ + c.Parameters.G2.GRootSigmaNeg.ScalarMultiplication(&c.Parameters.G2.GRootSigmaNeg, &deltaBI) + + // Update BasisExpSigma with δ⁻¹ + // TODO: Is it sound to use the same δ⁻¹ for all basis? + for i := 0; i < len(c.Parameters.G1.BasisExpSigma); i++ { + for j := 0; j < len(c.Parameters.G1.BasisExpSigma[i]); j++ { + c.Parameters.G1.BasisExpSigma[i][j].ScalarMultiplication( + &c.Parameters.G1.BasisExpSigma[i][j], + &deltaInvBI, + ) + } + } + // Update Z using δ⁻¹ for i := 0; i < len(c.Parameters.G1.Z); i++ { c.Parameters.G1.Z[i].ScalarMultiplication(&c.Parameters.G1.Z[i], &deltaInvBI) @@ -220,6 +284,14 @@ func VerifyPhase2(c0, c1 *Phase2, c ...*Phase2) error { } func verifyPhase2(current, contribution *Phase2) error { + // Check hash of the contribution + h := contribution.hash() + for i := 0; i < len(h); i++ { + if h[i] != contribution.Hash[i] { + return errors.New("couldn't verify hash of contribution") + } + } + // Compute R for δ deltaR := genR(contribution.PublicKey.SG, contribution.PublicKey.SXG, current.Hash[:], 1) @@ -232,7 +304,12 @@ func verifyPhase2(current, contribution *Phase2) error { if !sameRatio(contribution.Parameters.G1.Delta, current.Parameters.G1.Delta, deltaR, contribution.PublicKey.XR) { return errors.New("couldn't verify that [δ]₁ is based on previous contribution") } - if !sameRatio(contribution.PublicKey.SG, contribution.PublicKey.SXG, contribution.Parameters.G2.Delta, current.Parameters.G2.Delta) { + if !sameRatio( + contribution.PublicKey.SG, + contribution.PublicKey.SXG, + contribution.Parameters.G2.Delta, + current.Parameters.G2.Delta, + ) { return errors.New("couldn't verify that [δ]₂ is based on previous contribution") } @@ -246,11 +323,26 @@ func verifyPhase2(current, contribution *Phase2) error { return errors.New("couldn't verify valid updates of L using δ⁻¹") } - // Check hash of the contribution - h := contribution.hash() - for i := 0; i < len(h); i++ { - if h[i] != contribution.Hash[i] { - return errors.New("couldn't verify hash of contribution") + // Check for valid update of the pedersen key + if !sameRatio( + current.Parameters.G1.Delta, + contribution.Parameters.G1.Delta, + contribution.Parameters.G2.GRootSigmaNeg, + current.Parameters.G2.GRootSigmaNeg, + ) { + return errors.New("couldn't verify that GRootSigmaNeg is based on previous contribution") + } + for i := 0; i < len(current.Parameters.G1.BasisExpSigma); i++ { + basisExpSigma, prevBasisExpSigma := merge( + contribution.Parameters.G1.BasisExpSigma[i], + current.Parameters.G1.BasisExpSigma[i], + ) + if !sameRatio( + basisExpSigma, + prevBasisExpSigma, + contribution.Parameters.G2.Delta, current.Parameters.G2.Delta, + ) { + return errors.New("couldn't verify valid updates of BasisExpSigma using δ⁻¹") } } @@ -262,3 +354,28 @@ func (c *Phase2) hash() []byte { c.writeTo(sha) return sha.Sum(nil) } + +func InitPedersen(bases ...[]curve.G1Affine) (BasisExpSigma [][]curve.G1Affine, GRootSigmaNeg curve.G2Affine) { + _, _, _, g2 := curve.Generators() + + var modMinusOne big.Int + modMinusOne.Sub(fr.Modulus(), big.NewInt(1)) + + // set sigma to 1 + sigma := big.NewInt(1) + + // Todo: simplify + var sigmaInvNeg big.Int + sigmaInvNeg.ModInverse(sigma, fr.Modulus()) + sigmaInvNeg.Sub(fr.Modulus(), &sigmaInvNeg) + GRootSigmaNeg.ScalarMultiplication(&g2, &sigmaInvNeg) + + BasisExpSigma = make([][]curve.G1Affine, len(bases)) + for i := range bases { + BasisExpSigma[i] = make([]curve.G1Affine, len(bases[i])) + for j := range bases[i] { + BasisExpSigma[i][j].ScalarMultiplication(&bases[i][j], sigma) + } + } + return +} diff --git a/backend/groth16/bn254/mpcsetup/setup.go b/backend/groth16/bn254/mpcsetup/setup.go index 4946e9f597..3357f711d5 100644 --- a/backend/groth16/bn254/mpcsetup/setup.go +++ b/backend/groth16/bn254/mpcsetup/setup.go @@ -19,14 +19,20 @@ package mpcsetup import ( curve "github.com/consensys/gnark-crypto/ecc/bn254" "github.com/consensys/gnark-crypto/ecc/bn254/fr/fft" + "github.com/consensys/gnark-crypto/ecc/bn254/fr/pedersen" groth16 "github.com/consensys/gnark/backend/groth16/bn254" + "github.com/consensys/gnark/constraint" + cs "github.com/consensys/gnark/constraint/bn254" ) -func ExtractKeys(srs1 *Phase1, srs2 *Phase2, evals *Phase2Evaluations, nConstraints int) (pk groth16.ProvingKey, vk groth16.VerifyingKey) { +func ExtractKeys(r1cs *cs.R1CS, srs1 *Phase1, srs2 *Phase2, evals *Phase2Evaluations) (pk groth16.ProvingKey, vk groth16.VerifyingKey) { _, _, _, g2 := curve.Generators() + commitmentInfo := r1cs.CommitmentInfo.(constraint.Groth16Commitments) + commitmentWires := commitmentInfo.CommitmentIndexes() + // Initialize PK - pk.Domain = *fft.NewDomain(uint64(nConstraints)) + pk.Domain = *fft.NewDomain(uint64(r1cs.NbConstraints)) pk.G1.Alpha.Set(&srs1.Parameters.G1.AlphaTau[0]) pk.G1.Beta.Set(&srs1.Parameters.G1.BetaTau[0]) pk.G1.Delta.Set(&srs2.Parameters.G1.Delta) @@ -37,6 +43,12 @@ func ExtractKeys(srs1 *Phase1, srs2 *Phase2, evals *Phase2Evaluations, nConstrai pk.G2.Beta.Set(&srs1.Parameters.G2.Beta) pk.G2.Delta.Set(&srs2.Parameters.G2.Delta) + pk.CommitmentKeys = make([]pedersen.ProvingKey, len(evals.G1.Basis)) + for i := range evals.G1.Basis { + pk.CommitmentKeys[i].Basis = evals.G1.Basis[i] + pk.CommitmentKeys[i].BasisExpSigma = srs2.Parameters.G1.BasisExpSigma[i] + } + // Filter out infinity points nWires := len(evals.G1.A) pk.InfinityA = make([]bool, nWires) @@ -87,6 +99,9 @@ func ExtractKeys(srs1 *Phase1, srs2 *Phase2, evals *Phase2Evaluations, nConstrai vk.G2.Delta.Set(&srs2.Parameters.G2.Delta) vk.G2.Gamma.Set(&g2) vk.G1.K = evals.G1.VKK + vk.CommitmentKey.G = g2 + vk.CommitmentKey.GRootSigmaNeg = srs2.Parameters.G2.GRootSigmaNeg + vk.PublicAndCommitmentCommitted = commitmentInfo.GetPublicAndCommitmentCommitted(commitmentWires, r1cs.GetNbPublicVariables()) // sets e, -[δ]2, -[γ]2 if err := vk.Precompute(); err != nil { diff --git a/backend/groth16/bn254/mpcsetup/setup_test.go b/backend/groth16/bn254/mpcsetup/setup_test.go index 63b717cac4..76f35c8381 100644 --- a/backend/groth16/bn254/mpcsetup/setup_test.go +++ b/backend/groth16/bn254/mpcsetup/setup_test.go @@ -17,20 +17,148 @@ package mpcsetup import ( + "crypto/rand" + "math/big" + "testing" + + "github.com/consensys/gnark-crypto/ecc" curve "github.com/consensys/gnark-crypto/ecc/bn254" "github.com/consensys/gnark-crypto/ecc/bn254/fr" cs "github.com/consensys/gnark/constraint/bn254" - "testing" + "github.com/consensys/gnark/test" + "github.com/consensys/gnark-crypto/ecc/bn254/ecdsa" "github.com/consensys/gnark/backend/groth16" + "github.com/consensys/gnark/backend/witness" + bn254 "github.com/consensys/gnark/constraint/bn254" "github.com/consensys/gnark/frontend" "github.com/consensys/gnark/frontend/cs/r1cs" + "github.com/consensys/gnark/std/algebra/emulated/sw_emulated" "github.com/consensys/gnark/std/hash/mimc" + "github.com/consensys/gnark/std/math/emulated" + sig "github.com/consensys/gnark/std/signature/ecdsa" "github.com/stretchr/testify/require" native_mimc "github.com/consensys/gnark-crypto/ecc/bn254/fr/mimc" ) +type EcdsaCircuit[T, S emulated.FieldParams] struct { + Sig sig.Signature[S] + Msg emulated.Element[S] + Pub sig.PublicKey[T, S] +} + +func (c *EcdsaCircuit[T, S]) Define(api frontend.API) error { + c.Pub.Verify(api, sw_emulated.GetCurveParams[T](), &c.Msg, &c.Sig) + return nil +} + +func buildEcdsa() (*bn254.R1CS, *witness.Witness, error) { + // defer the closing of our jsonFile so that we can parse it later on + privKey, _ := ecdsa.GenerateKey(rand.Reader) + publicKey := privKey.PublicKey + + // sign + msg := []byte("testing ECDSA (pre-hashed)") + sigBin, _ := privKey.Sign(msg, nil) + + // check that the signature is correct + _, err := publicKey.Verify(sigBin, msg, nil) + if err != nil { + return nil, nil, err + } + + // unmarshal signature + var signature ecdsa.Signature + signature.SetBytes(sigBin) + r, s := new(big.Int), new(big.Int) + r.SetBytes(signature.R[:32]) + s.SetBytes(signature.S[:32]) + + hash := ecdsa.HashToInt(msg) + + circuit := EcdsaCircuit[emulated.BN254Fp, emulated.BN254Fr]{} + w := EcdsaCircuit[emulated.BN254Fp, emulated.BN254Fr]{ + Sig: sig.Signature[emulated.BN254Fr]{ + R: emulated.ValueOf[emulated.BN254Fr](r), + S: emulated.ValueOf[emulated.BN254Fr](s), + }, + Msg: emulated.ValueOf[emulated.BN254Fr](hash), + Pub: sig.PublicKey[emulated.BN254Fp, emulated.BN254Fr]{ + X: emulated.ValueOf[emulated.BN254Fp](privKey.PublicKey.A.X), + Y: emulated.ValueOf[emulated.BN254Fp](privKey.PublicKey.A.Y), + }, + } + + err = test.IsSolved(&circuit, &w, ecc.BN254.ScalarField()) + if err != nil { + return nil, nil, err + } + + witness, err := frontend.NewWitness(&w, ecc.BN254.ScalarField()) + if err != nil { + return nil, nil, err + } + + r1cs, err := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &circuit) + if err != nil { + return nil, nil, err + } + + return r1cs.(*bn254.R1CS), &witness, err +} + +func TestEcdsa(t *testing.T) { + const ( + nContributionsPhase1 = 3 + nContributionsPhase2 = 3 + power = 17 + ) + + assert := require.New(t) + + srs1 := InitPhase1(power) + + // Make and verify contributions for phase1 + for i := 1; i < nContributionsPhase1; i++ { + // we clone test purposes; but in practice, participant will receive a []byte, deserialize it, + // add his contribution and send back to coordinator. + prev := srs1.clone() + + srs1.Contribute() + assert.NoError(VerifyPhase1(&prev, &srs1)) + } + + r1cs, witness, err := buildEcdsa() + if err != nil { + t.Fatal(err) + } + + srs2, evals := InitPhase2(r1cs, &srs1) + + // Make and verify contributions for phase1 + for i := 1; i < nContributionsPhase2; i++ { + // we clone for test purposes; but in practice, participant will receive a []byte, deserialize it, + // add his contribution and send back to coordinator. + prev := srs2.clone() + + srs2.Contribute() + assert.NoError(VerifyPhase2(&prev, &srs2)) + } + + // Extract the proving and verifying keys + pk, vk := ExtractKeys(r1cs, &srs1, &srs2, &evals) + + proof, err := groth16.Prove(r1cs, &pk, *witness) + assert.NoError(err) + + pubWitness, err := (*witness).Public() + assert.NoError(err) + + err = groth16.Verify(proof, &vk, pubWitness) + assert.NoError(err) +} + func TestSetupCircuit(t *testing.T) { const ( nContributionsPhase1 = 3 @@ -74,7 +202,7 @@ func TestSetupCircuit(t *testing.T) { } // Extract the proving and verifying keys - pk, vk := ExtractKeys(&srs1, &srs2, &evals, ccs.GetNbConstraints()) + pk, vk := ExtractKeys(ccs.(*cs.R1CS), &srs1, &srs2, &evals) // Build the witness var preImage, hash fr.Element @@ -115,7 +243,6 @@ func BenchmarkPhase1(b *testing.B) { srs1.Contribute() } }) - } func BenchmarkPhase2(b *testing.B) { @@ -145,7 +272,6 @@ func BenchmarkPhase2(b *testing.B) { srs2.Contribute() } }) - } // Circuit defines a pre-image knowledge proof @@ -164,7 +290,6 @@ func (circuit *Circuit) Define(api frontend.API) error { // specify constraints mimc.Write(circuit.PreImage) api.AssertIsEqual(circuit.Hash, mimc.Sum()) - return nil } @@ -185,10 +310,18 @@ func (phase1 *Phase1) clone() Phase1 { func (phase2 *Phase2) clone() Phase2 { r := Phase2{} + r.Parameters.G1.BasisExpSigma = make([][]curve.G1Affine, len(r.Parameters.G1.BasisExpSigma)) + for i := 0; i < len(r.Parameters.G1.BasisExpSigma); i++ { + r.Parameters.G1.BasisExpSigma[i] = append( + r.Parameters.G1.BasisExpSigma[i], + phase2.Parameters.G1.BasisExpSigma[i]..., + ) + } r.Parameters.G1.Delta = phase2.Parameters.G1.Delta r.Parameters.G1.L = append(r.Parameters.G1.L, phase2.Parameters.G1.L...) r.Parameters.G1.Z = append(r.Parameters.G1.Z, phase2.Parameters.G1.Z...) r.Parameters.G2.Delta = phase2.Parameters.G2.Delta + r.Parameters.G2.GRootSigmaNeg = phase2.Parameters.G2.GRootSigmaNeg r.PublicKey = phase2.PublicKey r.Hash = append(r.Hash, phase2.Hash...)