Documentation ¶
Overview ¶
Package pedersen allows to compute and verify Pedersen vector commitments
Pedersen vector commitments are a type of homomorphic commitments that allow to commit to a vector of values and prove knowledge of the committed values. The commitments can be batched and verified in a single operation.
The commitments are computed using a set of basis elements. The proving key contains the basis elements and their exponentiations by a random value. The verifying key contains the G2 generator and its exponentiation by the inverse of the random value.
The setup process is a trusted setup and must be done securely, preferably using MPC. After the setup, the proving key does not have to be secret, but the randomness used during the setup must be discarded.
Example (SingleProof) ¶
This example demonstrates how to use the Pedersen commitment scheme to commit to a set of values and prove knowledge of the committed values.
Does not perform any batching or multi-proof optimization.
const nbElem = 4 // create a proving key with independent basis elements var buf [32]byte basis := make([]curve.G1Affine, nbElem) for i := range basis { _, err := rand.Read(buf[:]) if err != nil { panic(err) } // we use hash-to-curve to avoid linear dependencies between basis elements basis[i], err = curve.HashToG1(buf[:], []byte(fmt.Sprintf("basis %d", i))) if err != nil { panic(err) } } // create a proving and verifying key. NB! Must be done using MPC pks, vk, err := Setup([][]curve.G1Affine{basis}) if err != nil { panic(err) } // currently we only have a single proving key pk := pks[0] toCommit := make([]fr.Element, nbElem) for i := range toCommit { toCommit[i].SetRandom() } // commit to the values commitment, err := pk.Commit(toCommit) if err != nil { panic(err) } // prove knowledge of the committed values pok, err := pk.ProveKnowledge(toCommit) if err != nil { panic(err) } // verify the proof if err := vk.Verify(commitment, pok); err != nil { panic(err) } fmt.Println("verified")
Output: verified
Index ¶
- func BatchProve(pk []ProvingKey, values [][]fr.Element, combinationCoeff fr.Element) (pok curve.G1Affine, err error)
- func BatchVerifyMultiVk(vk []VerifyingKey, commitments []curve.G1Affine, pok []curve.G1Affine, ...) error
- func Setup(bases [][]curve.G1Affine, options ...SetupOption) (pk []ProvingKey, vk VerifyingKey, err error)
- type ProvingKey
- func (pk *ProvingKey) Commit(values []fr.Element) (commitment curve.G1Affine, err error)
- func (pk *ProvingKey) ProveKnowledge(values []fr.Element) (pok curve.G1Affine, err error)
- func (pk *ProvingKey) ReadFrom(r io.Reader) (int64, error)
- func (pk *ProvingKey) WriteRawTo(w io.Writer) (int64, error)
- func (pk *ProvingKey) WriteTo(w io.Writer) (int64, error)
- type SetupOption
- type VerifyingKey
- func (vk *VerifyingKey) ReadFrom(r io.Reader) (int64, error)
- func (vk *VerifyingKey) UnsafeReadFrom(r io.Reader) (int64, error)
- func (vk *VerifyingKey) Verify(commitment curve.G1Affine, knowledgeProof curve.G1Affine) error
- func (vk *VerifyingKey) WriteRawTo(w io.Writer) (int64, error)
- func (vk *VerifyingKey) WriteTo(w io.Writer) (int64, error)
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func BatchProve ¶ added in v0.11.2
func BatchProve(pk []ProvingKey, values [][]fr.Element, combinationCoeff fr.Element) (pok curve.G1Affine, err error)
BatchProve computes a single proof of knowledge for multiple commitments. The single PoK can be verified with a single call to VerifyingKey.Verify with folded commitments. The commitments can be folded into one using curve.G1Affine.Fold.
The argument combinationCoeff is used as a linear combination coefficient to fold separate proofs into one. It must be the same for batch proving and when folding commitments. This means that in an interactive setting, it must be randomly generated by the verifier and sent to the prover. Otherwise, it must be generated via Fiat-Shamir.
Example ¶
This example shows how to batch the commitment and proof generation.
const nbPks = 3 const nbElem = 4 // create a proving key with independent basis elements var buf [32]byte basis := make([][]curve.G1Affine, nbPks) for i := range basis { basis[i] = make([]curve.G1Affine, nbElem) for j := range basis[i] { _, err := rand.Read(buf[:]) if err != nil { panic(err) } // we use hash-to-curve to avoid linear dependencies between basis elements basis[i][j], err = curve.HashToG1(buf[:], []byte(fmt.Sprintf("basis %d", i))) if err != nil { panic(err) } } } // create a proving and verifying key. NB! Must be done using MPC pks, vk, err := Setup(basis) if err != nil { panic(err) } // generate random values to commit to toCommit := make([][]fr.Element, nbPks) for i := range toCommit { toCommit[i] = make([]fr.Element, nbElem) for j := range toCommit[i] { toCommit[i][j].SetRandom() } } // commit to the values commitments := make([]curve.G1Affine, nbPks) for i := range commitments { commitments[i], err = pks[i].Commit(toCommit[i]) if err != nil { panic(err) } } // combination coefficient is randomly sampled by the verifier. NB! In non-interactive protocol use Fiat-Shamir! var combinationCoeff fr.Element combinationCoeff.SetRandom() proof, err := BatchProve(pks, toCommit, combinationCoeff) if err != nil { panic(err) } // fold the commitments foldedCommitment, err := new(curve.G1Affine).Fold(commitments, combinationCoeff, ecc.MultiExpConfig{NbTasks: 1}) if err != nil { panic(err) } // verify the proof if err := vk.Verify(*foldedCommitment, proof); err != nil { panic(err) } fmt.Println("verified")
Output: verified
func BatchVerifyMultiVk ¶ added in v0.14.0
func BatchVerifyMultiVk(vk []VerifyingKey, commitments []curve.G1Affine, pok []curve.G1Affine, combinationCoeff fr.Element) error
BatchVerifyMultiVk verifies multiple separate proofs of knowledge using n+1 pairings instead of 2n pairings.
The verifying keys may be from different setup ceremonies, but the G2 point must be the same. This can be enforced using WithG2Point option during setup.
The argument combinationCoeff is used as a linear combination coefficient to fold separate proofs into one. This means that in an interactive setting, it must be randomly generated by the verifier and sent to the prover. Otherwise, it must be generated via Fiat-Shamir.
The prover can fold the proofs using curve.G1Affine.Fold itself using the random challenge, providing the verifier only the folded proof. In this case the argument pok should contain only the single folded proof.
Example ¶
This example shows how to batch verify multiple proofs using multiple verifying keys.
const nbPks = 3 const nbElem = 4 // create a proving key with independent basis elements var buf [32]byte basis := make([][]curve.G1Affine, nbPks) for i := range basis { basis[i] = make([]curve.G1Affine, nbElem) for j := range basis[i] { _, err := rand.Read(buf[:]) if err != nil { panic(err) } // we use hash-to-curve to avoid linear dependencies between basis elements basis[i][j], err = curve.HashToG1(buf[:], []byte(fmt.Sprintf("basis %d", i))) if err != nil { panic(err) } } } // we create independent proving keys (different sigmas) with same G2 // g2Point does not have to be generated in a trusted manner _, _, _, g2Point := curve.Generators() pks := make([]ProvingKey, nbPks) vks := make([]VerifyingKey, nbPks) for i := range basis { pkss, vkss, err := Setup(basis[i:i+1], WithG2Point(g2Point)) if err != nil { panic(err) } pks[i] = pkss[0] vks[i] = vkss } // generate random values to commit to toCommit := make([][]fr.Element, nbPks) for i := range toCommit { toCommit[i] = make([]fr.Element, nbElem) for j := range toCommit[i] { toCommit[i][j].SetRandom() } } // commit to the values commitments := make([]curve.G1Affine, nbPks) for i := range commitments { var err error commitments[i], err = pks[i].Commit(toCommit[i]) if err != nil { panic(err) } } // prove the commitments proofs := make([]curve.G1Affine, nbPks) for i := range proofs { var err error proofs[i], err = pks[i].ProveKnowledge(toCommit[i]) if err != nil { panic(err) } } // combination coefficient is randomly sampled by the verifier. NB! In non-interactive protocol use Fiat-Shamir! var combinationCoeff fr.Element combinationCoeff.SetRandom() // batch verify the proofs if err := BatchVerifyMultiVk(vks, commitments, proofs, combinationCoeff); err != nil { panic(err) } // alternatively, we can also provide the folded proof foldedProof, err := new(curve.G1Affine).Fold(proofs, combinationCoeff, ecc.MultiExpConfig{NbTasks: 1}) if err != nil { panic(err) } if err := BatchVerifyMultiVk(vks, commitments, []curve.G1Affine{*foldedProof}, combinationCoeff); err != nil { panic(err) } fmt.Println("verified")
Output: verified
func Setup ¶
func Setup(bases [][]curve.G1Affine, options ...SetupOption) (pk []ProvingKey, vk VerifyingKey, err error)
Setup generates the proving keys for Pedersen commitments over the given bases allowing for batch proving. The common verifying key can be used to verify the batched proof of knowledge.
By default the G2 generator is sampled randomly. This can be overridden by providing a custom G2 generator using WithG2Point option.
The input bases do not have to be of the same length for individual committing and proving. The elements in bases[i] should be linearly independent of each other. Otherwise the prover may be able to construct multiple valid openings for a commitment.
NB! This is a trusted setup process. The randomness during the setup must be discarded. Failing to do so allows to create proofs without knowing the committed values.
Types ¶
type ProvingKey ¶ added in v0.11.0
type ProvingKey struct { Basis []curve.G1Affine BasisExpSigma []curve.G1Affine // basisExpSigma[i] = Basis[i]^{σ} }
ProvingKey for committing and proofs of knowledge
func (*ProvingKey) Commit ¶ added in v0.11.0
Commit computes a commitment to the values over proving key's basis
func (*ProvingKey) ProveKnowledge ¶ added in v0.11.2
ProveKnowledge generates a proof of knowledge of a commitment to the given values over proving key's basis.
func (*ProvingKey) ReadFrom ¶ added in v0.11.0
func (pk *ProvingKey) ReadFrom(r io.Reader) (int64, error)
func (*ProvingKey) WriteRawTo ¶ added in v0.11.2
func (pk *ProvingKey) WriteRawTo(w io.Writer) (int64, error)
type SetupOption ¶ added in v0.14.0
type SetupOption func(cfg *setupConfig)
SetupOption allows to customize Pedersen vector commitment setup.
func WithG2Point ¶ added in v0.14.0
func WithG2Point(g2 curve.G2Affine) SetupOption
WithG2Point allows to set the G2 generator for the Pedersen vector commitment setup. If this is not set, we sample a random G2 point.
type VerifyingKey ¶ added in v0.11.0
func (*VerifyingKey) ReadFrom ¶ added in v0.11.0
func (vk *VerifyingKey) ReadFrom(r io.Reader) (int64, error)
func (*VerifyingKey) UnsafeReadFrom ¶ added in v0.11.2
func (vk *VerifyingKey) UnsafeReadFrom(r io.Reader) (int64, error)
func (*VerifyingKey) Verify ¶ added in v0.11.0
Verify checks if the proof of knowledge is valid for a given commitment.
func (*VerifyingKey) WriteRawTo ¶ added in v0.11.2
func (vk *VerifyingKey) WriteRawTo(w io.Writer) (int64, error)