sw_bn254

package
v0.10.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 22, 2024 License: Apache-2.0 Imports: 9 Imported by: 15

Documentation

Overview

Package sw_bn254 implements G1 and G2 arithmetics and pairing computation over BN254 curve.

The implementation follows [Housni22]: "Pairings in Rank-1 Constraint Systems".

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type BaseField added in v0.10.0

type BaseField = emulated.BN254Fp

BaseField is the emulated.FieldParams impelementation of the curve base field.

type G1Affine

type G1Affine = sw_emulated.AffinePoint[BaseField]

G1Affine is the point in G1. It is an alias to the generic emulated affine point.

func NewG1Affine

func NewG1Affine(v bn254.G1Affine) G1Affine

NewG1Affine allocates a witness from the native G1 element and returns it.

type G2

type G2 struct {
	*fields_bn254.Ext2
	// contains filtered or unexported fields
}

func NewG2

func NewG2(api frontend.API) *G2

func (*G2) AssertIsEqual

func (g2 *G2) AssertIsEqual(p, q *G2Affine)

AssertIsEqual asserts that p and q are the same point.

type G2Affine

type G2Affine struct {
	P     g2AffP
	Lines *lineEvaluations
}

G2Affine represents G2 element with optional embedded line precomputations.

func NewG2Affine

func NewG2Affine(v bn254.G2Affine) G2Affine

func NewG2AffineFixed added in v0.10.0

func NewG2AffineFixed(v bn254.G2Affine) G2Affine

NewG2AffineFixed returns witness of v with precomputations for efficient pairing computation.

func NewG2AffineFixedPlaceholder added in v0.10.0

func NewG2AffineFixedPlaceholder() G2Affine

NewG2AffineFixedPlaceholder returns a placeholder for the circuit compilation when witness will be given with line precomputations using NewG2AffineFixed.

type GTEl

type GTEl = fields_bn254.E12

func NewGTEl

func NewGTEl(v bn254.GT) GTEl

type Pairing

type Pairing struct {
	*fields_bn254.Ext12
	// contains filtered or unexported fields
}
Example
package main

import (
	"crypto/rand"
	"fmt"

	"github.com/consensys/gnark-crypto/ecc"
	"github.com/consensys/gnark-crypto/ecc/bn254"
	"github.com/consensys/gnark/backend/groth16"
	"github.com/consensys/gnark/frontend"
	"github.com/consensys/gnark/frontend/cs/r1cs"
	"github.com/consensys/gnark/std/algebra/emulated/sw_bn254"
)

type PairCircuit struct {
	InG1 sw_bn254.G1Affine
	InG2 sw_bn254.G2Affine
	Res  sw_bn254.GTEl
}

func (c *PairCircuit) Define(api frontend.API) error {
	pairing, err := sw_bn254.NewPairing(api)
	if err != nil {
		return fmt.Errorf("new pairing: %w", err)
	}
	// Pair method does not check that the points are in the proper groups.
	pairing.AssertIsOnG1(&c.InG1)
	pairing.AssertIsOnG2(&c.InG2)
	// Compute the pairing
	res, err := pairing.Pair([]*sw_bn254.G1Affine{&c.InG1}, []*sw_bn254.G2Affine{&c.InG2})
	if err != nil {
		return fmt.Errorf("pair: %w", err)
	}
	pairing.AssertIsEqual(res, &c.Res)
	return nil
}

func main() {
	p, q, err := randomG1G2Affines()
	if err != nil {
		panic(err)
	}
	res, err := bn254.Pair([]bn254.G1Affine{p}, []bn254.G2Affine{q})
	if err != nil {
		panic(err)
	}
	circuit := PairCircuit{}
	witness := PairCircuit{
		InG1: sw_bn254.NewG1Affine(p),
		InG2: sw_bn254.NewG2Affine(q),
		Res:  sw_bn254.NewGTEl(res),
	}
	ccs, err := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &circuit)
	if err != nil {
		panic(err)
	}
	pk, vk, err := groth16.Setup(ccs)
	if err != nil {
		panic(err)
	}
	secretWitness, err := frontend.NewWitness(&witness, ecc.BN254.ScalarField())
	if err != nil {
		panic(err)
	}
	publicWitness, err := secretWitness.Public()
	if err != nil {
		panic(err)
	}
	proof, err := groth16.Prove(ccs, pk, secretWitness)
	if err != nil {
		panic(err)
	}
	err = groth16.Verify(proof, vk, publicWitness)
	if err != nil {
		panic(err)
	}
}

func randomG1G2Affines() (p bn254.G1Affine, q bn254.G2Affine, err error) {
	_, _, G1AffGen, G2AffGen := bn254.Generators()
	mod := bn254.ID.ScalarField()
	s1, err := rand.Int(rand.Reader, mod)
	if err != nil {
		return p, q, err
	}
	s2, err := rand.Int(rand.Reader, mod)
	if err != nil {
		return p, q, err
	}
	p.ScalarMultiplication(&G1AffGen, s1)
	q.ScalarMultiplication(&G2AffGen, s2)
	return
}
Output:

func NewPairing

func NewPairing(api frontend.API) (*Pairing, error)

func (Pairing) AssertIsEqual

func (pr Pairing) AssertIsEqual(x, y *GTEl)

func (Pairing) AssertIsOnCurve

func (pr Pairing) AssertIsOnCurve(P *G1Affine)

func (Pairing) AssertIsOnG1

func (pr Pairing) AssertIsOnG1(P *G1Affine)

func (Pairing) AssertIsOnG2

func (pr Pairing) AssertIsOnG2(Q *G2Affine)

func (Pairing) AssertIsOnTwist

func (pr Pairing) AssertIsOnTwist(Q *G2Affine)

func (Pairing) FinalExponentiation

func (pr Pairing) FinalExponentiation(e *GTEl) *GTEl

FinalExponentiation computes the exponentiation eᵈ where

d = (p¹²-1)/r = (p¹²-1)/Φ₁₂(p) ⋅ Φ₁₂(p)/r = (p⁶-1)(p²+1)(p⁴ - p² +1)/r.

We use instead d'= s ⋅ d, where s is the cofactor

2x₀(6x₀²+3x₀+1)

and r does NOT divide d'

FinalExponentiation returns a decompressed element in E12.

This is the safe version of the method where e may be {-1,1}. If it is known that e ≠ {-1,1} then using the unsafe version of the method saves considerable amount of constraints. When called with the result of [MillerLoop], then current method is applicable when length of the inputs to Miller loop is 1.

func (Pairing) FinalExponentiationIsOne

func (pr Pairing) FinalExponentiationIsOne(e *GTEl)

FinalExponentiationIsOne performs the final exponentiation on e and checks that the result in 1 in GT.

This method is needed for evmprecompiles/ecpair.

func (Pairing) FinalExponentiationUnsafe

func (pr Pairing) FinalExponentiationUnsafe(e *GTEl) *GTEl

FinalExponentiationUnsafe computes the exponentiation eᵈ where

d = (p¹²-1)/r = (p¹²-1)/Φ₁₂(p) ⋅ Φ₁₂(p)/r = (p⁶-1)(p²+1)(p⁴ - p² +1)/r.

We use instead d'= s ⋅ d, where s is the cofactor

2x₀(6x₀²+3x₀+1)

and r does NOT divide d'

FinalExponentiationUnsafe returns a decompressed element in E12.

This is the unsafe version of the method where e may NOT be {-1,1}. If e ∈ {-1, 1}, then there exists no valid solution to the circuit. This method is applicable when called with the result of [MillerLoop] method when the length of the inputs to Miller loop is 1.

func (Pairing) MillerLoop

func (pr Pairing) MillerLoop(P []*G1Affine, Q []*G2Affine) (*GTEl, error)

MillerLoop computes the multi-Miller loop ∏ᵢ { fᵢ_{6x₀+2,Q}(P) · ℓᵢ_{[6x₀+2]Q,π(Q)}(P) · ℓᵢ_{[6x₀+2]Q+π(Q),-π²(Q)}(P) }

func (Pairing) MillerLoopAndMul

func (pr Pairing) MillerLoopAndMul(P *G1Affine, Q *G2Affine, previous *GTEl) (*GTEl, error)

MillerLoopAndMul computes the Miller loop between P and Q and multiplies it in 𝔽p¹² by previous.

This method is needed for evmprecompiles/ecpair.

func (Pairing) Pair

func (pr Pairing) Pair(P []*G1Affine, Q []*G2Affine) (*GTEl, error)

Pair calculates the reduced pairing for a set of points ∏ᵢ e(Pᵢ, Qᵢ).

This function doesn't check that the inputs are in the correct subgroups. See AssertIsOnG1 and AssertIsOnG2.

func (Pairing) PairingCheck

func (pr Pairing) PairingCheck(P []*G1Affine, Q []*G2Affine) error

PairingCheck calculates the reduced pairing for a set of points and asserts if the result is One ∏ᵢ e(Pᵢ, Qᵢ) =? 1

This function doesn't check that the inputs are in the correct subgroups. See AssertIsOnG1 and AssertIsOnG2.

type Scalar added in v0.9.1

type Scalar = emulated.Element[ScalarField]

Scalar is the scalar in the groups. It is an alias to the emulated element defined over the scalar field of the groups.

func NewScalar added in v0.9.1

func NewScalar(v fr_bn254.Element) Scalar

NewScalar allocates a witness from the native scalar and returns it.

type ScalarField added in v0.10.0

type ScalarField = emulated.BN254Fr

ScalarField is the emulated.FieldParams impelementation of the curve scalar field.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL