-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
statetransition: integration test stub
- Loading branch information
Showing
2 changed files
with
211 additions
and
0 deletions.
There are no files selected for viewing
177 changes: 177 additions & 0 deletions
177
circuits/test/statetransition/statetransition_inputs.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,177 @@ | ||
package statetransitiontest | ||
|
||
import ( | ||
"fmt" | ||
"math" | ||
"math/big" | ||
|
||
"github.com/consensys/gnark-crypto/ecc" | ||
fr_bw6761 "github.com/consensys/gnark-crypto/ecc/bw6-761/fr" | ||
bw6761mimc "github.com/consensys/gnark-crypto/ecc/bw6-761/fr/mimc" | ||
"github.com/consensys/gnark/backend/groth16" | ||
"github.com/consensys/gnark/frontend" | ||
"github.com/consensys/gnark/frontend/cs/r1cs" | ||
"github.com/consensys/gnark/std/algebra/native/sw_bls12377" | ||
"github.com/consensys/gnark/std/math/emulated/emparams" | ||
stdgroth16 "github.com/consensys/gnark/std/recursion/groth16" | ||
"github.com/vocdoni/vocdoni-z-sandbox/circuits" | ||
"github.com/vocdoni/vocdoni-z-sandbox/circuits/aggregator" | ||
"github.com/vocdoni/vocdoni-z-sandbox/circuits/statetransition" | ||
aggregatortest "github.com/vocdoni/vocdoni-z-sandbox/circuits/test/aggregator" | ||
ballottest "github.com/vocdoni/vocdoni-z-sandbox/circuits/test/ballotproof" | ||
) | ||
|
||
// StateTransitionTestResults struct includes relevant data after StateTransitionCircuit | ||
// inputs generation, including the encrypted ballots in both formats: matrix | ||
// and plain (for hashing) | ||
type StateTransitionTestResults struct { | ||
ProcessId []byte | ||
CensusRoot *big.Int | ||
EncryptionPubKey [2]*big.Int | ||
Nullifiers []*big.Int | ||
Commitments []*big.Int | ||
Addresses []*big.Int | ||
EncryptedBallots [][ballottest.NFields][2][2]*big.Int | ||
PlainEncryptedBallots []*big.Int | ||
} | ||
|
||
// StateTransitionInputsForTest returns the StateTransitionTestResults, the placeholder | ||
// and the assigments of a StateTransitionCircuit for the processId provided | ||
// generating nValidVoters. If something fails it returns an error. | ||
func StateTransitionInputsForTest(processId []byte, nValidVoters int) ( | ||
*StateTransitionTestResults, *statetransition.Circuit, *statetransition.Circuit, error, | ||
) { | ||
// generate aggregator circuit and inputs | ||
agInputs, agPlaceholder, agWitness, err := aggregatortest.AggregarorInputsForTest(processId, nValidVoters) | ||
if err != nil { | ||
return nil, nil, nil, err | ||
} | ||
// compile aggregoar circuit | ||
agCCS, err := frontend.Compile(ecc.BLS12_377.ScalarField(), r1cs.NewBuilder, agPlaceholder) | ||
if err != nil { | ||
return nil, nil, nil, err | ||
} | ||
agPk, agVk, err := groth16.Setup(agCCS) | ||
if err != nil { | ||
return nil, nil, nil, err | ||
} | ||
// generate voters proofs | ||
proofInBLS12377 := stdgroth16.Proof[sw_bls12377.G1Affine, sw_bls12377.G2Affine]{} | ||
pubInputs := stdgroth16.Witness[emparams.BLS12377Fr]{} | ||
// parse the witness to the circuit | ||
fullWitness, err := frontend.NewWitness(agWitness, ecc.BLS12_377.ScalarField()) | ||
if err != nil { | ||
return nil, nil, nil, err | ||
} | ||
// generate the proof | ||
proof, err := groth16.Prove(agCCS, agPk, fullWitness, stdgroth16.GetNativeProverOptions(ecc.BW6_761.ScalarField(), ecc.BLS12_377.ScalarField())) | ||
if err != nil { | ||
return nil, nil, nil, fmt.Errorf("err proving proof: %w", err) | ||
} | ||
// convert the proof to the circuit proof type | ||
proofInBLS12377, err = stdgroth16.ValueOfProof[sw_bls12377.G1Affine, sw_bls12377.G2Affine](proof) | ||
if err != nil { | ||
return nil, nil, nil, err | ||
} | ||
// convert the public inputs to the circuit public inputs type | ||
publicWitness, err := fullWitness.Public() | ||
if err != nil { | ||
return nil, nil, nil, err | ||
} | ||
err = groth16.Verify(proof, agVk, publicWitness, stdgroth16.GetNativeVerifierOptions(ecc.BW6_761.ScalarField(), ecc.BLS12_377.ScalarField())) | ||
if err != nil { | ||
return nil, nil, nil, err | ||
} | ||
pubInputs, err = stdgroth16.ValueOfWitness[sw_bls12377.ScalarField](publicWitness) | ||
if err != nil { | ||
return nil, nil, nil, err | ||
} | ||
// compute public inputs hash | ||
inputs := []*big.Int{ | ||
new(big.Int).SetBytes(agInputs.ProcessId), | ||
agInputs.CensusRoot, | ||
// ballotMode(), // TODO: serialize ballotmode into a bigint? or flatten it? | ||
agInputs.EncryptionPubKey[0], | ||
agInputs.EncryptionPubKey[1], | ||
} | ||
// pad voters inputs (nullifiers, commitments, addresses, plain EncryptedBallots) | ||
nullifiers := circuits.BigIntArrayToN(agInputs.Nullifiers, aggregator.MaxVotes) | ||
commitments := circuits.BigIntArrayToN(agInputs.Commitments, aggregator.MaxVotes) | ||
addresses := circuits.BigIntArrayToN(agInputs.Addresses, aggregator.MaxVotes) | ||
plainEncryptedBallots := circuits.BigIntArrayToN(agInputs.PlainEncryptedBallots, aggregator.MaxVotes*ballottest.NFields*4) | ||
// append voters inputs (nullifiers, commitments, addresses, plain EncryptedBallots) | ||
inputs = append(inputs, nullifiers...) | ||
inputs = append(inputs, commitments...) | ||
inputs = append(inputs, addresses...) | ||
inputs = append(inputs, plainEncryptedBallots...) | ||
// hash the inputs to generate the inputs hash | ||
var buf [fr_bw6761.Bytes]byte | ||
aggregatorHashFn := bw6761mimc.NewMiMC() | ||
for _, input := range inputs { | ||
input.FillBytes(buf[:]) | ||
_, err := aggregatorHashFn.Write(buf[:]) | ||
if err != nil { | ||
return nil, nil, nil, err | ||
} | ||
} | ||
publicHash := new(big.Int).SetBytes(aggregatorHashFn.Sum(nil)) | ||
// init final assigments stuff | ||
finalAssigments := &statetransition.Circuit{ | ||
InputsHash: publicHash, | ||
ValidVotes: aggregator.EncodeProofsSelector(nValidVoters), | ||
BallotMode: circuits.BallotMode[frontend.Variable]{ | ||
Check failure on line 122 in circuits/test/statetransition/statetransition_inputs.go GitHub Actions / job_go_test
|
||
MaxCount: ballottest.MaxCount, | ||
ForceUniqueness: ballottest.ForceUniqueness, | ||
MaxValue: ballottest.MaxValue, | ||
MinValue: ballottest.MinValue, | ||
MaxTotalCost: int(math.Pow(float64(ballottest.MaxValue), float64(ballottest.CostExp))) * ballottest.MaxCount, | ||
MinTotalCost: ballottest.MaxCount, | ||
CostExp: ballottest.CostExp, | ||
CostFromWeight: ballottest.CostFromWeight, | ||
EncryptionPubKey: [2]frontend.Variable{agInputs.EncryptionPubKey[0], agInputs.EncryptionPubKey[1]}, | ||
}, | ||
ProcessId: new(big.Int).SetBytes(agInputs.ProcessId), | ||
CensusRoot: agInputs.CensusRoot, | ||
VerifyProofs: proofInBLS12377, | ||
VerifyPublicInputs: pubInputs, | ||
} | ||
// set voters final witness stuff | ||
for i := 0; i < nValidVoters; i++ { | ||
finalAssigments.Nullifiers[i] = agInputs.Nullifiers[i] | ||
finalAssigments.Commitments[i] = agInputs.Commitments[i] | ||
finalAssigments.Addresses[i] = new(big.Int).SetBytes(vvData[i].Address.Bytes()) | ||
for j := 0; j < ballottest.NFields; j++ { | ||
for n := 0; n < 2; n++ { | ||
for m := 0; m < 2; m++ { | ||
finalAssigments.EncryptedBallots[i][j][n][m] = agInputs.EncryptedBallots[i][j][n][m] | ||
} | ||
} | ||
} | ||
} | ||
// create final placeholder | ||
finalPlaceholder := &statetransition.Circuit{ | ||
AggregatedProofWitness: stdgroth16.Witness[sw_bls12377.ScalarField]{}, | ||
AggregatedProof: stdgroth16.Proof[sw_bls12377.G1Affine, sw_bls12377.G2Affine]{}, | ||
AggregatedProofVK: stdgroth16.VerifyingKey[sw_bls12377.G1Affine, sw_bls12377.G2Affine, sw_bls12377.GT]{}, | ||
} | ||
// fix the vote verifier verification key | ||
fixedVk, err := stdgroth16.ValueOfVerifyingKeyFixed[sw_bls12377.G1Affine, sw_bls12377.G2Affine, sw_bls12377.GT](agVk) | ||
if err != nil { | ||
return nil, nil, nil, err | ||
} | ||
finalPlaceholder.AggregatedProofVK = fixedVk | ||
// // fill placeholder and witness with dummy circuits | ||
// if err := aggregator.FillWithDummyFixed(finalPlaceholder, finalAssigments, agCCS, nValidVoters); err != nil { | ||
// return nil, nil, nil, err | ||
// } | ||
return &StateTransitionTestResults{ | ||
ProcessId: agInputs.ProcessId, | ||
CensusRoot: agInputs.CensusRoot, | ||
EncryptionPubKey: agInputs.EncryptionPubKey, | ||
Nullifiers: nullifiers, | ||
Commitments: commitments, | ||
Addresses: addresses, | ||
EncryptedBallots: agInputs.EncryptedBallots, | ||
PlainEncryptedBallots: plainEncryptedBallots, | ||
}, finalPlaceholder, finalAssigments, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package statetransitiontest | ||
|
||
import ( | ||
"os" | ||
"testing" | ||
"time" | ||
|
||
"github.com/consensys/gnark-crypto/ecc" | ||
"github.com/consensys/gnark/backend" | ||
stdgroth16 "github.com/consensys/gnark/std/recursion/groth16" | ||
"github.com/consensys/gnark/test" | ||
qt "github.com/frankban/quicktest" | ||
"github.com/vocdoni/vocdoni-z-sandbox/util" | ||
) | ||
|
||
func TestStateTransitionCircuit(t *testing.T) { | ||
if os.Getenv("RUN_CIRCUIT_TESTS") == "" || os.Getenv("RUN_CIRCUIT_TESTS") == "false" { | ||
t.Skip("skipping circuit tests...") | ||
} | ||
c := qt.New(t) | ||
// inputs generation | ||
now := time.Now() | ||
processId := util.RandomBytes(20) | ||
_, placeholder, witness, err := StateTransitionInputsForTest(processId, 3) | ||
c.Assert(err, qt.IsNil) | ||
c.Logf("inputs generation took %s", time.Since(now).String()) | ||
// proving | ||
now = time.Now() | ||
assert := test.NewAssert(t) | ||
assert.SolvingSucceeded(placeholder, witness, | ||
test.WithCurves(ecc.BW6_761), test.WithBackends(backend.GROTH16), | ||
test.WithProverOpts(stdgroth16.GetNativeProverOptions(ecc.BN254.ScalarField(), ecc.BW6_761.ScalarField()))) | ||
c.Logf("proving took %s", time.Since(now).String()) | ||
} |