-
Notifications
You must be signed in to change notification settings - Fork 227
feat: Poseidon2 Hash Instantiation for BLS12-377 #623
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
22 commits
Select commit
Hold shift + click to select a range
b0836b1
feat: poseidon2 hash e2e
Tabaie 6e98abf
build: generify
Tabaie ef9d20d
revert: make parameters private
Tabaie 19afe00
fix: match seed with gnark
Tabaie d67ae5d
feat: register poseidon2 for bls12377
Tabaie 5f6f607
feat: add gkr gates
Tabaie a7ee00b
refactor: powerFr -> sBox
Tabaie 4ee4ae2
Merge branch 'master' into feat/poseidon2-hash
Tabaie 6342bca
fix: sBox2 route correct output
Tabaie 6f9e706
chore: gofmt
ivokub 3a59d34
refactor: rename the interface to Compresser
ivokub 4b2437a
docs: package docs
ivokub 8d34901
docs: add package docs
ivokub 58013e4
feat: disable cases except T=2,3
ivokub 37e1989
refactor: rename hash to permutation
ivokub 7f7fb1c
chore: go generate
ivokub fad1a4e
fix: spell error
ivokub 6f5a265
refactor: make sbox degree constant
ivokub e57cabb
refactor: Poseidon package
ivokub fd958f1
chore: go generate
ivokub fdbe624
refactor: make parameter representation public
ivokub ba65635
refactor: move gates to separate package
ivokub File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or 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,193 @@ | ||
| // Package gkrgates implements the Poseidon2 permutation gate for GKR | ||
| // | ||
| // This implementation is based on the [poseidon2] package, but exposes the | ||
| // primitives as gates for inclusion in GKR circuits. | ||
|
|
||
| // TODO(@Tabaie @ThomasPiellard) generify once Poseidon2 parameters are known for all curves | ||
| package gkrgates | ||
|
|
||
| import ( | ||
| "fmt" | ||
| "sync" | ||
|
|
||
| "github.com/consensys/gnark-crypto/ecc/bls12-377/fr" | ||
| "github.com/consensys/gnark-crypto/ecc/bls12-377/fr/gkr" | ||
| "github.com/consensys/gnark-crypto/ecc/bls12-377/fr/poseidon2" | ||
| ) | ||
|
|
||
| // The GKR gates needed for proving Poseidon2 permutations | ||
|
|
||
| // extKeySBoxGate applies the external matrix mul, then adds the round key, then applies the sBox | ||
| // because of its symmetry, we don't need to define distinct x1 and x2 versions of it | ||
| type extKeySBoxGate struct { | ||
| roundKey fr.Element | ||
| } | ||
|
|
||
| func (g *extKeySBoxGate) Evaluate(x ...fr.Element) fr.Element { | ||
| if len(x) != 2 { | ||
| panic("expected 2 inputs") | ||
| } | ||
|
|
||
| x[0]. | ||
| Double(&x[0]). | ||
| Add(&x[0], &x[1]). | ||
| Add(&x[0], &g.roundKey) | ||
| return sBox2(x[0]) | ||
| } | ||
|
|
||
| func (g *extKeySBoxGate) Degree() int { | ||
| return poseidon2.DegreeSBox() | ||
| } | ||
|
|
||
| // for x1, the partial round gates are identical to full round gates | ||
| // for x2, the partial round gates are just a linear combination | ||
| // TODO @Tabaie eliminate the x2 partial round gates and have the x1 gates depend on i - rf/2 or so previous x1's | ||
|
|
||
| // extGate2 applies the external matrix mul, outputting the second element of the result | ||
| type extGate2 struct{} | ||
|
|
||
| func (extGate2) Evaluate(x ...fr.Element) fr.Element { | ||
| if len(x) != 2 { | ||
| panic("expected 2 inputs") | ||
| } | ||
| x[1]. | ||
| Double(&x[1]). | ||
| Add(&x[1], &x[0]) | ||
| return x[1] | ||
| } | ||
|
|
||
| func (g extGate2) Degree() int { | ||
| return 1 | ||
| } | ||
|
|
||
| // intGate2 applies the internal matrix mul, returning the second element | ||
| type intGate2 struct { | ||
| } | ||
|
|
||
| func (g intGate2) Evaluate(x ...fr.Element) fr.Element { | ||
| if len(x) != 2 { | ||
| panic("expected 2 inputs") | ||
| } | ||
| x[0].Add(&x[0], &x[1]) | ||
| x[1]. | ||
| Double(&x[1]). | ||
| Add(&x[1], &x[0]) | ||
| return x[1] | ||
| } | ||
|
|
||
| func (g intGate2) Degree() int { | ||
| return 1 | ||
| } | ||
|
|
||
| // intKeySBoxGateFr applies the second row of internal matrix mul, then adds the round key, then applies the sBox | ||
| type intKeySBoxGate2 struct { | ||
| roundKey fr.Element | ||
| } | ||
|
|
||
| func (g *intKeySBoxGate2) Evaluate(x ...fr.Element) fr.Element { | ||
| if len(x) != 2 { | ||
| panic("expected 2 inputs") | ||
| } | ||
| x[0].Add(&x[0], &x[1]) | ||
| x[1]. | ||
| Double(&x[1]). | ||
| Add(&x[1], &x[0]). | ||
| Add(&x[1], &g.roundKey) | ||
|
|
||
| return sBox2(x[1]) | ||
| } | ||
|
|
||
| func (g *intKeySBoxGate2) Degree() int { | ||
| return poseidon2.DegreeSBox() | ||
| } | ||
|
|
||
| type extGate struct{} | ||
|
|
||
| func (g extGate) Evaluate(x ...fr.Element) fr.Element { | ||
| if len(x) != 2 { | ||
| panic("expected 2 inputs") | ||
| } | ||
| x[0]. | ||
| Double(&x[0]). | ||
| Add(&x[0], &x[1]) | ||
| return x[0] | ||
| } | ||
|
|
||
| func (g extGate) Degree() int { | ||
| return 1 | ||
| } | ||
|
|
||
| // sBox2 is Hash.sBox for t=2 | ||
| func sBox2(x fr.Element) fr.Element { | ||
| var y fr.Element | ||
| y.Square(&x).Square(&y).Square(&y).Square(&y).Mul(&x, &y) | ||
| return y | ||
| } | ||
|
|
||
| var initOnce sync.Once | ||
|
|
||
| // RegisterGkrGates registers the Poseidon2 permutation gates for GKR | ||
| func RegisterGkrGates() { | ||
| initOnce.Do( | ||
| func() { | ||
| p := poseidon2.NewDefaultParameters() | ||
| halfRf := p.NbFullRounds / 2 | ||
|
|
||
| gateNameX := func(i int) string { | ||
| return fmt.Sprintf("x-round=%d%s", i, p.String()) | ||
| } | ||
| gateNameY := func(i int) string { | ||
| return fmt.Sprintf("y-round=%d%s", i, p.String()) | ||
| } | ||
|
|
||
| fullRound := func(i int) { | ||
| gkr.Gates[gateNameX(i)] = &extKeySBoxGate{ | ||
| roundKey: p.RoundKeys[i][0], | ||
| } | ||
|
|
||
| gkr.Gates[gateNameY(i)] = &extKeySBoxGate{ | ||
| roundKey: p.RoundKeys[i][1], | ||
| } | ||
| } | ||
|
|
||
| for i := range halfRf { | ||
| fullRound(i) | ||
| } | ||
|
|
||
| { // i = halfRf: first partial round | ||
| i := halfRf | ||
| gkr.Gates[gateNameX(i)] = &extKeySBoxGate{ | ||
| roundKey: p.RoundKeys[i][0], | ||
| } | ||
|
|
||
| gkr.Gates[gateNameY(i)] = extGate2{} | ||
| } | ||
|
|
||
| for i := halfRf + 1; i < halfRf+p.NbPartialRounds; i++ { | ||
| gkr.Gates[gateNameX(i)] = &extKeySBoxGate{ // for x1, intKeySBox is identical to extKeySBox | ||
| roundKey: p.RoundKeys[i][0], | ||
| } | ||
|
|
||
| gkr.Gates[gateNameY(i)] = intGate2{} | ||
|
|
||
| } | ||
|
|
||
| { | ||
| i := halfRf + p.NbPartialRounds | ||
| gkr.Gates[gateNameX(i)] = &extKeySBoxGate{ | ||
| roundKey: p.RoundKeys[i][0], | ||
| } | ||
|
|
||
| gkr.Gates[gateNameY(i)] = &intKeySBoxGate2{ | ||
| roundKey: p.RoundKeys[i][1], | ||
| } | ||
| } | ||
|
|
||
| for i := halfRf + p.NbPartialRounds + 1; i < p.NbPartialRounds+p.NbFullRounds; i++ { | ||
| fullRound(i) | ||
| } | ||
|
|
||
| gkr.Gates[gateNameY(p.NbPartialRounds+p.NbFullRounds)] = extGate{} | ||
| }, | ||
| ) | ||
| } | ||
This file contains hidden or 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,31 @@ | ||
| package poseidon2 | ||
|
|
||
| import ( | ||
| "hash" | ||
|
|
||
| "github.com/consensys/gnark-crypto/ecc/bls12-377/fr" | ||
| gnarkHash "github.com/consensys/gnark-crypto/hash" | ||
| ) | ||
|
|
||
| // NewMerkleDamgardHasher returns a Poseidon2 hasher using the Merkle-Damgard | ||
| // construction with the default parameters. | ||
| func NewMerkleDamgardHasher() gnarkHash.StateStorer { | ||
| // TODO @Tabaie @ThomasPiellard Generify once Poseidon2 parameters are known for all curves | ||
| return gnarkHash.NewMerkleDamgardHasher( | ||
| &Permutation{params: NewDefaultParameters()}, make([]byte, fr.Bytes)) | ||
| } | ||
|
|
||
| // NewParameters returns a new set of parameters for the Poseidon2 permutation. | ||
| // The default parameters are: | ||
| // - width: 2 | ||
| // - nbFullRounds: 6 | ||
| // - nbPartialRounds: 26 | ||
| func NewDefaultParameters() *Parameters { | ||
| return NewParameters(2, 6, 26) | ||
| } | ||
|
|
||
| func init() { | ||
| gnarkHash.RegisterHash(gnarkHash.POSEIDON2_BLS12_377, func() hash.Hash { | ||
| return NewMerkleDamgardHasher() | ||
| }) | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.