sw_bn254

package
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Feb 8, 2024 License: Apache-2.0 Imports: 9 Imported by: 0

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

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

func NewG2AffineFixed(v bn254.G2Affine) G2Affine

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

func NewG2AffineFixedPlaceholder

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

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

func NewScalar(v fr_bn254.Element) Scalar

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

type ScalarField

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