Skip to content

Commit

Permalink
add: permutation lazy expanding (Consensys#10)
Browse files Browse the repository at this point in the history
Co-authored-by: ZhAnGeek <lecky.z@nodereal.io>
  • Loading branch information
ZhAnGeek and ZhAnGeek authored Dec 16, 2022
1 parent b79c55c commit ad3959b
Show file tree
Hide file tree
Showing 17 changed files with 79 additions and 359 deletions.
6 changes: 5 additions & 1 deletion examples/rollup/circuit.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,11 @@ func (circuit *Circuit) Define(api frontend.API) error {
}

p := poseidon.Poseidon(api, circuit.Transfers[i].Nonce, circuit.Transfers[i].Amount)
poseidon.Poseidon(api, p, circuit.Transfers[i].Amount)
target := make([]frontend.Variable, 256)
for i := range target {
target[i] = p
}
poseidon.Poseidon(api, target...)

// update the accounts
verifyAccountUpdated(api, circuit.SenderAccountsBefore[i], circuit.ReceiverAccountsBefore[i], circuit.SenderAccountsAfter[i], circuit.ReceiverAccountsAfter[i], circuit.Transfers[i].Amount)
Expand Down
6 changes: 3 additions & 3 deletions internal/backend/bn254/cs/r1cs.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

46 changes: 35 additions & 11 deletions std/hash/poseidon/poseidon.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ package poseidon

import (
"github.com/consensys/gnark/backend/hint"
"github.com/consensys/gnark/frontend"
"github.com/consensys/gnark/frontend/compiled"
"github.com/consensys/gnark/std/hash/poseidon/constants"

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

// power 5 as s-box
Expand Down Expand Up @@ -98,18 +99,41 @@ func preHandleData(api frontend.API, data ...frontend.Variable) []frontend.Varia
return data
}

func Poseidon(api frontend.API, data ...frontend.Variable) frontend.Variable {
data = preHandleData(api, data...)
// we record 2 params first, then lets see if we can record multi params and solve
t := len(data) + 1
if t < 3 || t > 13 {
func Poseidon(api frontend.API, input ...frontend.Variable) frontend.Variable {
input = preHandleData(api, input...)
inputLength := len(input)
// No support for hashing inputs of length less than 2
if inputLength < 2 {
panic("Not supported input size")
}
vInternal := api.AddInternalVariableWithLazy(compiled.GetConstraintsNum(data, api))
api.AddLazyPoseidon(vInternal, data...)
state := make([]frontend.Variable, t)

const maxLength = 12
state := make([]frontend.Variable, maxLength+1)
state[0] = frontend.Variable(0)
copy(state[1:], data)
state = permutation(api, state)
startIndex := 0
lastIndex := 0

// Make a hash chain of the input if its length > maxLength
if inputLength > maxLength {
count := inputLength / maxLength
for i := 0; i < count; i++ {
lastIndex = (i + 1) * maxLength
copy(state[1:], input[startIndex:lastIndex])
v := api.AddInternalVariableWithLazy(compiled.GetConstraintsNum(state[1:], api))
api.AddLazyPoseidon(v, state[1:]...)
state = permutation(api, state)
startIndex = lastIndex
}
}

// For the remaining part of the input OR if 2 <= inputLength <= 12
if lastIndex < inputLength {
lastIndex = inputLength
remainigLength := lastIndex - startIndex
copy(state[1:], input[startIndex:lastIndex])
v := api.AddInternalVariableWithLazy(compiled.GetConstraintsNum(state[1:remainigLength+1], api))
api.AddLazyPoseidon(v, state[1:remainigLength+1]...)
state = permutation(api, state[:remainigLength+1])
}
return state[0]
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package poseidon_bak
package poseidon

import (
"math/big"
Expand Down Expand Up @@ -29,6 +29,11 @@ type poseidonCircuit30 struct {
Data [30]frontend.Variable
}

type poseidonCircuit256 struct {
Hash frontend.Variable `gnark:"data,public"`
Data [256]frontend.Variable
}

func (circuit *poseidonCircuit2) Define(api frontend.API) error {
result := Poseidon(api, circuit.Data[:]...)
api.AssertIsEqual(result, circuit.Hash)
Expand All @@ -52,9 +57,16 @@ func (circuit *poseidonCircuit30) Define(api frontend.API) error {
api.AssertIsEqual(result, circuit.Hash)
return nil
}

func (circuit *poseidonCircuit256) Define(api frontend.API) error {
result := Poseidon(api, circuit.Data[:]...)
api.AssertIsEqual(result, circuit.Hash)
return nil
}

func TestPoseidon2(t *testing.T) {
assert := test.NewAssert(t)
var circuit, witness, wrongWitness poseidonCircuit2
var circuit, witness poseidonCircuit2
hash, _ := new(big.Int).SetString("115cc0f5e7d690413df64c6b9662e9cf2a3617f2743245519e19607a4417189a", 16)

// Test completeness
Expand All @@ -63,14 +75,7 @@ func TestPoseidon2(t *testing.T) {
witness.Data[i] = frontend.Variable(i + 1)
}
witness.Hash = hash
assert.SolvingSucceeded(&circuit, &witness, test.WithCurves(ecc.BN254))

// Test soundness
for i := 0; i < size; i++ {
wrongWitness.Data[i] = frontend.Variable(i + 2)
}
wrongWitness.Hash = hash
assert.SolvingFailed(&circuit, &wrongWitness, test.WithCurves(ecc.BN254))
assert.SolvingSucceeded(&circuit, &witness, test.WithCurves(ecc.BN254), test.WithCompileOpts(frontend.IgnoreUnconstrainedInputs()))
}

func TestPoseidon4(t *testing.T) {
Expand Down Expand Up @@ -137,3 +142,24 @@ func TestPoseidon30(t *testing.T) {
wrongWitness.Hash = hash
assert.SolvingFailed(&circuit, &wrongWitness, test.WithCurves(ecc.BN254))
}

func TestPoseidon256(t *testing.T) {
assert := test.NewAssert(t)
var circuit, witness, wrongWitness poseidonCircuit256
hash, _ := new(big.Int).SetString("15b218692488b5ce4c9f8571e7daef78bd39cc455d431572f5f5f2933e4f5ea2", 16)

// Test completeness
size := 256
for i := 0; i < size; i++ {
witness.Data[i] = frontend.Variable(i + 1)
}
witness.Hash = hash
assert.SolvingSucceeded(&circuit, &witness, test.WithCurves(ecc.BN254))

// Test soundness
for i := 0; i < size; i++ {
wrongWitness.Data[i] = frontend.Variable(i + 2)
}
wrongWitness.Hash = hash
assert.SolvingFailed(&circuit, &wrongWitness, test.WithCurves(ecc.BN254))
}
45 changes: 0 additions & 45 deletions std/hash/poseidon_bak/constants/constants.go

This file was deleted.

10 changes: 0 additions & 10 deletions std/hash/poseidon_bak/constants/t10.go

This file was deleted.

10 changes: 0 additions & 10 deletions std/hash/poseidon_bak/constants/t11.go

This file was deleted.

10 changes: 0 additions & 10 deletions std/hash/poseidon_bak/constants/t12.go

This file was deleted.

10 changes: 0 additions & 10 deletions std/hash/poseidon_bak/constants/t13.go

This file was deleted.

Loading

0 comments on commit ad3959b

Please sign in to comment.