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 FoldCommitments(commitments []curve.G1Affine, combinationCoeff fr.Element) (commitment curve.G1Affine, err 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 ¶
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 FoldCommitments.
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 := FoldCommitments(commitments, combinationCoeff) 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 ¶
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.
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) } fmt.Println("verified")
Output: verified
func FoldCommitments ¶
func FoldCommitments(commitments []curve.G1Affine, combinationCoeff fr.Element) (commitment curve.G1Affine, err error)
FoldCommitments folds multiple commitments into a single commitment for verifying the batched proof computed with BatchProve.
The argument combinationCoeff is used as a linear combination coefficient to fold separate commitments 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.
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 ¶
type ProvingKey struct { Basis []curve.G1Affine BasisExpSigma []curve.G1Affine // basisExpSigma[i] = Basis[i]^{σ} }
ProvingKey for committing and proofs of knowledge
func (*ProvingKey) ProveKnowledge ¶
ProveKnowledge generates a proof of knowledge of a commitment to the given values over proving key's basis.
func (*ProvingKey) WriteRawTo ¶
func (pk *ProvingKey) WriteRawTo(w io.Writer) (int64, error)
type SetupOption ¶
type SetupOption func(cfg *setupConfig)
SetupOption allows to customize Pedersen vector commitment setup.
func WithG2Point ¶
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 ¶
type VerifyingKey struct { G curve.G2Affine GRootSigmaNeg curve.G2Affine // GRootSigmaNeg = G^{-1/σ} }
func (*VerifyingKey) UnsafeReadFrom ¶
func (vk *VerifyingKey) UnsafeReadFrom(r io.Reader) (int64, error)
func (*VerifyingKey) Verify ¶
Verify checks if the proof of knowledge is valid for a given commitment.
func (*VerifyingKey) WriteRawTo ¶
func (vk *VerifyingKey) WriteRawTo(w io.Writer) (int64, error)