github.com/ethereum/go-ethereum@v1.16.1/crypto/bn256/gnark/pairing.go (about)

     1  package bn256
     2  
     3  import (
     4  	"github.com/consensys/gnark-crypto/ecc/bn254"
     5  )
     6  
     7  // PairingCheck computes the following relation: ∏ᵢ e(Pᵢ, Qᵢ) =? 1
     8  //
     9  // To explain why gnark returns a (bool, error):
    10  //
    11  //   - If the function `e` does not return a result then internally
    12  //     an error is returned.
    13  //   - If `e` returns a result, then error will be nil,
    14  //     but if this value is not `1` then the boolean value will be false
    15  //
    16  // We therefore check for an error, and return false if its non-nil and
    17  // then return the value of the boolean if not.
    18  func PairingCheck(a_ []*G1, b_ []*G2) bool {
    19  	a := getInnerG1s(a_)
    20  	b := getInnerG2s(b_)
    21  
    22  	// Assume that len(a) == len(b)
    23  	//
    24  	// The pairing function will return
    25  	// false, if this is not the case.
    26  	size := len(a)
    27  
    28  	// Check if input is empty -- gnark will
    29  	// return false on an empty input, however
    30  	// the ossified behavior is to return true
    31  	// on an empty input, so we add this if statement.
    32  	if size == 0 {
    33  		return true
    34  	}
    35  
    36  	ok, err := bn254.PairingCheck(a, b)
    37  	if err != nil {
    38  		return false
    39  	}
    40  	return ok
    41  }
    42  
    43  // getInnerG1s gets the inner gnark G1 elements.
    44  //
    45  // These methods are used for two reasons:
    46  //
    47  //   - We use a new type `G1`, so we need to convert from
    48  //     []*G1 to []*bn254.G1Affine
    49  //   - The gnark API accepts slices of values and not slices of
    50  //     pointers to values, so we need to return []bn254.G1Affine
    51  //     instead of []*bn254.G1Affine.
    52  func getInnerG1s(pointerSlice []*G1) []bn254.G1Affine {
    53  	gnarkValues := make([]bn254.G1Affine, 0, len(pointerSlice))
    54  	for _, ptr := range pointerSlice {
    55  		if ptr != nil {
    56  			gnarkValues = append(gnarkValues, ptr.inner)
    57  		}
    58  	}
    59  	return gnarkValues
    60  }
    61  
    62  // getInnerG2s gets the inner gnark G2 elements.
    63  //
    64  // The rationale for this method is the same as `getInnerG1s`.
    65  func getInnerG2s(pointerSlice []*G2) []bn254.G2Affine {
    66  	gnarkValues := make([]bn254.G2Affine, 0, len(pointerSlice))
    67  	for _, ptr := range pointerSlice {
    68  		if ptr != nil {
    69  			gnarkValues = append(gnarkValues, ptr.inner)
    70  		}
    71  	}
    72  	return gnarkValues
    73  }