Skip to content

Commit

Permalink
init changes
Browse files Browse the repository at this point in the history
incomplete
  • Loading branch information
dcbuild3r committed Aug 30, 2023
1 parent 71637c0 commit d74c313
Show file tree
Hide file tree
Showing 7 changed files with 464 additions and 139 deletions.
9 changes: 5 additions & 4 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@ package main
import (
"encoding/json"
"fmt"
gnarkLogger "github.com/consensys/gnark/logger"
"github.com/urfave/cli/v2"
"io"
"math/big"
"os"
"os/signal"
"worldcoin/gnark-mbu/logging"
"worldcoin/gnark-mbu/prover"
"worldcoin/gnark-mbu/server"

gnarkLogger "github.com/consensys/gnark/logger"
"github.com/urfave/cli/v2"
)

func main() {
Expand Down Expand Up @@ -104,7 +105,7 @@ func main() {
},
},
{
Name: "gen-test-params",
Name: "gen-test-params-insertion",
Flags: []cli.Flag{
&cli.UintFlag{Name: "tree-depth", Usage: "depth of the mock tree", Required: true},
&cli.UintFlag{Name: "batch-size", Usage: "batch size", Required: true},
Expand All @@ -126,7 +127,7 @@ func main() {
params.MerkleProofs[i] = tree.Update(i, params.IdComms[i])
}
params.PostRoot = tree.Root()
params.ComputeInputHash()
params.ComputeInputHashInsertion()
r, _ := json.Marshal(&params)
fmt.Println(string(r))
return nil
Expand Down
112 changes: 21 additions & 91 deletions prover/circuit.go → prover/circuit_utils.go
Original file line number Diff line number Diff line change
@@ -1,32 +1,29 @@
package prover

import (
"io"
"strconv"
"worldcoin/gnark-mbu/prover/keccak"
"worldcoin/gnark-mbu/prover/poseidon"

"github.com/consensys/gnark/backend/groth16"
"github.com/consensys/gnark/constraint"
"github.com/consensys/gnark/frontend"
)

const emptyLeaf = 0

type MbuCircuit struct {
// single public input
InputHash frontend.Variable `gnark:",public"`

// private inputs, but used as public inputs
StartIndex frontend.Variable `gnark:"input"`
PreRoot frontend.Variable `gnark:"input"`
PostRoot frontend.Variable `gnark:"input"`
IdComms []frontend.Variable `gnark:"input"`

// private inputs
MerkleProofs [][]frontend.Variable `gnark:"input"`
type Proof struct {
Proof groth16.Proof
}

BatchSize int
Depth int
type ProvingSystem struct {
TreeDepth uint32
BatchSize uint32
ProvingKey groth16.ProvingKey
VerifyingKey groth16.VerifyingKey
ConstraintSystem constraint.ConstraintSystem
}

const emptyLeaf = 0

type bitPatternLengthError struct {
actualLength int
}
Expand Down Expand Up @@ -106,80 +103,13 @@ func FromBinaryBigEndian(bitsBigEndian []frontend.Variable, api frontend.API) (v
return api.FromBinary(bitsLittleEndian...), nil
}

func (circuit *MbuCircuit) Define(api frontend.API) error {
// Hash private inputs.
// We keccak hash all input to save verification gas. Inputs are arranged as follows:
// StartIndex || PreRoot || PostRoot || IdComms[0] || IdComms[1] || ... || IdComms[batchSize-1]
// 32 || 256 || 256 || 256 || 256 || ... || 256 bits

kh := keccak.NewKeccak256(api, (circuit.BatchSize+2)*256+32)

var bits []frontend.Variable
var err error

// We convert all the inputs to the keccak hash to use big-endian (network) byte
// ordering so that it agrees with Solidity. This ensures that we don't have to
// perform the conversion inside the contract and hence save on gas.
bits, err = ToBinaryBigEndian(circuit.StartIndex, 32, api)
if err != nil {
return err
}
kh.Write(bits...)

bits, err = ToBinaryBigEndian(circuit.PreRoot, 256, api)
if err != nil {
return err
func toBytesLE(b []byte) []byte {
for i := 0; i < len(b)/2; i++ {
b[i], b[len(b)-i-1] = b[len(b)-i-1], b[i]
}
kh.Write(bits...)

bits, err = ToBinaryBigEndian(circuit.PostRoot, 256, api)
if err != nil {
return err
}
kh.Write(bits...)

for i := 0; i < circuit.BatchSize; i++ {
bits, err = ToBinaryBigEndian(circuit.IdComms[i], 256, api)
if err != nil {
return err
}
kh.Write(bits...)
}

var sum frontend.Variable
sum, err = FromBinaryBigEndian(kh.Sum(), api)
if err != nil {
return err
}

// The same endianness conversion has been performed in the hash generation
// externally, so we can safely assert their equality here.
api.AssertIsEqual(circuit.InputHash, sum)

// Actual batch merkle proof verification.
var root frontend.Variable
ph := poseidon.NewPoseidon2(api)

prevRoot := circuit.PreRoot

// Individual insertions.
for i := 0; i < circuit.BatchSize; i += 1 {
currentIndex := api.Add(circuit.StartIndex, i)
currentPath := api.ToBinary(currentIndex, circuit.Depth)

// Verify proof for empty leaf.
root = VerifyProof(api, ph, append([]frontend.Variable{emptyLeaf}, circuit.MerkleProofs[i][:]...), currentPath)
api.AssertIsEqual(root, prevRoot)

// Verify proof for idComm.
root = VerifyProof(api, ph, append([]frontend.Variable{circuit.IdComms[i]}, circuit.MerkleProofs[i][:]...), currentPath)

// Set root for next iteration.
prevRoot = root
}

// Final root needs to match.
api.AssertIsEqual(root, circuit.PostRoot)
return b
}

return nil
func (ps *ProvingSystem) ExportSolidity(writer io.Writer) error {
return ps.VerifyingKey.ExportSolidity(writer)
}
93 changes: 93 additions & 0 deletions prover/deletion_circuit.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package prover

import (
"worldcoin/gnark-mbu/prover/keccak"
"worldcoin/gnark-mbu/prover/poseidon"

"github.com/consensys/gnark/frontend"
)

type DeletionMbuCircuit struct {
// single public input
InputHash frontend.Variable `gnark:",public"`

// private inputs, but used as public inputs
DeletionIndices []frontend.Variable `gnark:"input"`
PreRoot frontend.Variable `gnark:"input"`
PostRoot frontend.Variable `gnark:"input"`

// private inputs
IdComms []frontend.Variable `gnark:"input"`
MerkleProofs [][]frontend.Variable `gnark:"input"`

BatchSize int
Depth int
}

func (circuit *DeletionMbuCircuit) Define(api frontend.API) error {
// Hash private inputs.
// We keccak hash all input to save verification gas. Inputs are arranged as follows:
// deletionIndices[0] || deletionIndices[1] || ... || deletionIndices[batchSize-1] || PreRoot || PostRoot
// 32 || 32 || ... || 32 || 256 || 256

kh := keccak.NewKeccak256(api, circuit.BatchSize*32+2*256)

var bits []frontend.Variable
var err error

for i := 0; i < circuit.BatchSize; i++ {
bits, err = ToBinaryBigEndian(circuit.DeletionIndices[i], 32, api)
if err != nil {
return err
}
kh.Write(bits...)
}

bits, err = ToBinaryBigEndian(circuit.PreRoot, 256, api)
if err != nil {
return err
}
kh.Write(bits...)

bits, err = ToBinaryBigEndian(circuit.PostRoot, 256, api)
if err != nil {
return err
}
kh.Write(bits...)

var sum frontend.Variable
sum, err = FromBinaryBigEndian(kh.Sum(), api)
if err != nil {
return err
}

// The same endianness conversion has been performed in the hash generation
// externally, so we can safely assert their equality here.
api.AssertIsEqual(circuit.InputHash, sum)

// Actual batch merkle proof verification.
var root frontend.Variable
ph := poseidon.NewPoseidon2(api)

prevRoot := circuit.PreRoot

// Individual insertions.
for i := 0; i < circuit.BatchSize; i += 1 {
currentPath := api.ToBinary(circuit.DeletionIndices[i], circuit.Depth)

// Verify proof for empty leaf.
root = VerifyProof(api, ph, append([]frontend.Variable{circuit.IdComms[i]}, circuit.MerkleProofs[i][:]...), currentPath)
api.AssertIsEqual(root, prevRoot)

// Verify proof for idComm.
root = VerifyProof(api, ph, append([]frontend.Variable{emptyLeaf}, circuit.MerkleProofs[i][:]...), currentPath)

// Set root for next iteration.
prevRoot = root
}

// Final root needs to match.
api.AssertIsEqual(root, circuit.PostRoot)

return nil
}
Loading

0 comments on commit d74c313

Please sign in to comment.