| 
									
										
											  
											
												core/vm, crypto/bls12381, params: add bls12-381 elliptic curve precompiles (#21018)
* crypto: add bls12-381 elliptic curve wrapper
* params: add bls12-381 precompile gas parameters
* core/vm: add bls12-381 precompiles
* core/vm: add bls12-381 precompile tests
* go.mod, go.sum: use latest bls12381 lib
* core/vm: move point encode/decode functions to base library
* crypto/bls12381: introduce bls12-381 library init function
* crypto/bls12381: import bls12381 elliptic curve implementation
* go.mod, go.sum: remove bls12-381 library
* remove unsued frobenious coeffs
supress warning for inp that used in asm
* add mappings tests for zero inputs
fix swu g2 minus z inverse constant
* crypto/bls12381: fix typo
* crypto/bls12381: better comments for bls12381 constants
* crypto/bls12381: swu, use single conditional for e2
* crypto/bls12381: utils, delete empty line
* crypto/bls12381: utils, use FromHex for string to big
* crypto/bls12381: g1, g2, strict length check for FromBytes
* crypto/bls12381: field_element, comparision changes
* crypto/bls12381: change swu, isogeny constants with hex values
* core/vm: fix point multiplication comments
* core/vm: fix multiexp gas calculation and lookup for g1 and g2
* core/vm: simpler imput length check for multiexp and pairing precompiles
* core/vm: rm empty multiexp result declarations
* crypto/bls12381: remove modulus type definition
* crypto/bls12381: use proper init function
* crypto/bls12381: get rid of new lines at fatal desciprtions
* crypto/bls12-381: fix no-adx assembly multiplication
* crypto/bls12-381: remove old config function
* crypto/bls12381: update multiplication backend
this commit changes mul backend to 6limb eip1962 backend
mul assign operations are dropped
* core/vm/contracts_tests: externalize test vectors for precompiles
* core/vm/contracts_test: externalize failure-cases for precompiles
* core/vm: linting
* go.mod: tiny up sum file
* core/vm: fix goimports linter issues
* crypto/bls12381: build tags for plain ASM or ADX implementation
Co-authored-by: Martin Holst Swende <martin@swende.se>
Co-authored-by: Péter Szilágyi <peterke@gmail.com>
											
										 
											2020-06-03 09:44:32 +03:00
										 |  |  | // Copyright 2020 The go-ethereum Authors | 
					
						
							|  |  |  | // This file is part of the go-ethereum library. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // The go-ethereum library is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  | // it under the terms of the GNU Lesser General Public License as published by | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | // (at your option) any later version. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // The go-ethereum library is distributed in the hope that it will be useful, | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 
					
						
							|  |  |  | // GNU Lesser General Public License for more details. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // You should have received a copy of the GNU Lesser General Public License | 
					
						
							|  |  |  | // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package bls12381 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"errors" | 
					
						
							|  |  |  | 	"math/big" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type fp2Temp struct { | 
					
						
							|  |  |  | 	t [4]*fe | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type fp2 struct { | 
					
						
							|  |  |  | 	fp2Temp | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func newFp2Temp() fp2Temp { | 
					
						
							|  |  |  | 	t := [4]*fe{} | 
					
						
							|  |  |  | 	for i := 0; i < len(t); i++ { | 
					
						
							|  |  |  | 		t[i] = &fe{} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return fp2Temp{t} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func newFp2() *fp2 { | 
					
						
							|  |  |  | 	t := newFp2Temp() | 
					
						
							|  |  |  | 	return &fp2{t} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (e *fp2) fromBytes(in []byte) (*fe2, error) { | 
					
						
							|  |  |  | 	if len(in) != 96 { | 
					
						
							| 
									
										
										
										
											2020-06-08 09:53:19 +02:00
										 |  |  | 		return nil, errors.New("length of input string should be 96 bytes") | 
					
						
							| 
									
										
											  
											
												core/vm, crypto/bls12381, params: add bls12-381 elliptic curve precompiles (#21018)
* crypto: add bls12-381 elliptic curve wrapper
* params: add bls12-381 precompile gas parameters
* core/vm: add bls12-381 precompiles
* core/vm: add bls12-381 precompile tests
* go.mod, go.sum: use latest bls12381 lib
* core/vm: move point encode/decode functions to base library
* crypto/bls12381: introduce bls12-381 library init function
* crypto/bls12381: import bls12381 elliptic curve implementation
* go.mod, go.sum: remove bls12-381 library
* remove unsued frobenious coeffs
supress warning for inp that used in asm
* add mappings tests for zero inputs
fix swu g2 minus z inverse constant
* crypto/bls12381: fix typo
* crypto/bls12381: better comments for bls12381 constants
* crypto/bls12381: swu, use single conditional for e2
* crypto/bls12381: utils, delete empty line
* crypto/bls12381: utils, use FromHex for string to big
* crypto/bls12381: g1, g2, strict length check for FromBytes
* crypto/bls12381: field_element, comparision changes
* crypto/bls12381: change swu, isogeny constants with hex values
* core/vm: fix point multiplication comments
* core/vm: fix multiexp gas calculation and lookup for g1 and g2
* core/vm: simpler imput length check for multiexp and pairing precompiles
* core/vm: rm empty multiexp result declarations
* crypto/bls12381: remove modulus type definition
* crypto/bls12381: use proper init function
* crypto/bls12381: get rid of new lines at fatal desciprtions
* crypto/bls12-381: fix no-adx assembly multiplication
* crypto/bls12-381: remove old config function
* crypto/bls12381: update multiplication backend
this commit changes mul backend to 6limb eip1962 backend
mul assign operations are dropped
* core/vm/contracts_tests: externalize test vectors for precompiles
* core/vm/contracts_test: externalize failure-cases for precompiles
* core/vm: linting
* go.mod: tiny up sum file
* core/vm: fix goimports linter issues
* crypto/bls12381: build tags for plain ASM or ADX implementation
Co-authored-by: Martin Holst Swende <martin@swende.se>
Co-authored-by: Péter Szilágyi <peterke@gmail.com>
											
										 
											2020-06-03 09:44:32 +03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	c1, err := fromBytes(in[:48]) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	c0, err := fromBytes(in[48:]) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return &fe2{*c0, *c1}, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (e *fp2) toBytes(a *fe2) []byte { | 
					
						
							|  |  |  | 	out := make([]byte, 96) | 
					
						
							|  |  |  | 	copy(out[:48], toBytes(&a[1])) | 
					
						
							|  |  |  | 	copy(out[48:], toBytes(&a[0])) | 
					
						
							|  |  |  | 	return out | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (e *fp2) new() *fe2 { | 
					
						
							|  |  |  | 	return new(fe2).zero() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (e *fp2) zero() *fe2 { | 
					
						
							|  |  |  | 	return new(fe2).zero() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (e *fp2) one() *fe2 { | 
					
						
							|  |  |  | 	return new(fe2).one() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (e *fp2) add(c, a, b *fe2) { | 
					
						
							|  |  |  | 	add(&c[0], &a[0], &b[0]) | 
					
						
							|  |  |  | 	add(&c[1], &a[1], &b[1]) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (e *fp2) addAssign(a, b *fe2) { | 
					
						
							|  |  |  | 	addAssign(&a[0], &b[0]) | 
					
						
							|  |  |  | 	addAssign(&a[1], &b[1]) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (e *fp2) ladd(c, a, b *fe2) { | 
					
						
							|  |  |  | 	ladd(&c[0], &a[0], &b[0]) | 
					
						
							|  |  |  | 	ladd(&c[1], &a[1], &b[1]) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (e *fp2) double(c, a *fe2) { | 
					
						
							|  |  |  | 	double(&c[0], &a[0]) | 
					
						
							|  |  |  | 	double(&c[1], &a[1]) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (e *fp2) doubleAssign(a *fe2) { | 
					
						
							|  |  |  | 	doubleAssign(&a[0]) | 
					
						
							|  |  |  | 	doubleAssign(&a[1]) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (e *fp2) ldouble(c, a *fe2) { | 
					
						
							|  |  |  | 	ldouble(&c[0], &a[0]) | 
					
						
							|  |  |  | 	ldouble(&c[1], &a[1]) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (e *fp2) sub(c, a, b *fe2) { | 
					
						
							|  |  |  | 	sub(&c[0], &a[0], &b[0]) | 
					
						
							|  |  |  | 	sub(&c[1], &a[1], &b[1]) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (e *fp2) subAssign(c, a *fe2) { | 
					
						
							|  |  |  | 	subAssign(&c[0], &a[0]) | 
					
						
							|  |  |  | 	subAssign(&c[1], &a[1]) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (e *fp2) neg(c, a *fe2) { | 
					
						
							|  |  |  | 	neg(&c[0], &a[0]) | 
					
						
							|  |  |  | 	neg(&c[1], &a[1]) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (e *fp2) mul(c, a, b *fe2) { | 
					
						
							|  |  |  | 	t := e.t | 
					
						
							|  |  |  | 	mul(t[1], &a[0], &b[0]) | 
					
						
							|  |  |  | 	mul(t[2], &a[1], &b[1]) | 
					
						
							|  |  |  | 	add(t[0], &a[0], &a[1]) | 
					
						
							|  |  |  | 	add(t[3], &b[0], &b[1]) | 
					
						
							|  |  |  | 	sub(&c[0], t[1], t[2]) | 
					
						
							|  |  |  | 	addAssign(t[1], t[2]) | 
					
						
							|  |  |  | 	mul(t[0], t[0], t[3]) | 
					
						
							|  |  |  | 	sub(&c[1], t[0], t[1]) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (e *fp2) mulAssign(a, b *fe2) { | 
					
						
							|  |  |  | 	t := e.t | 
					
						
							|  |  |  | 	mul(t[1], &a[0], &b[0]) | 
					
						
							|  |  |  | 	mul(t[2], &a[1], &b[1]) | 
					
						
							|  |  |  | 	add(t[0], &a[0], &a[1]) | 
					
						
							|  |  |  | 	add(t[3], &b[0], &b[1]) | 
					
						
							|  |  |  | 	sub(&a[0], t[1], t[2]) | 
					
						
							|  |  |  | 	addAssign(t[1], t[2]) | 
					
						
							|  |  |  | 	mul(t[0], t[0], t[3]) | 
					
						
							|  |  |  | 	sub(&a[1], t[0], t[1]) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (e *fp2) square(c, a *fe2) { | 
					
						
							|  |  |  | 	t := e.t | 
					
						
							|  |  |  | 	ladd(t[0], &a[0], &a[1]) | 
					
						
							|  |  |  | 	sub(t[1], &a[0], &a[1]) | 
					
						
							|  |  |  | 	ldouble(t[2], &a[0]) | 
					
						
							|  |  |  | 	mul(&c[0], t[0], t[1]) | 
					
						
							|  |  |  | 	mul(&c[1], t[2], &a[1]) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (e *fp2) squareAssign(a *fe2) { | 
					
						
							|  |  |  | 	t := e.t | 
					
						
							|  |  |  | 	ladd(t[0], &a[0], &a[1]) | 
					
						
							|  |  |  | 	sub(t[1], &a[0], &a[1]) | 
					
						
							|  |  |  | 	ldouble(t[2], &a[0]) | 
					
						
							|  |  |  | 	mul(&a[0], t[0], t[1]) | 
					
						
							|  |  |  | 	mul(&a[1], t[2], &a[1]) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (e *fp2) mulByNonResidue(c, a *fe2) { | 
					
						
							|  |  |  | 	t := e.t | 
					
						
							|  |  |  | 	sub(t[0], &a[0], &a[1]) | 
					
						
							|  |  |  | 	add(&c[1], &a[0], &a[1]) | 
					
						
							|  |  |  | 	c[0].set(t[0]) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (e *fp2) mulByB(c, a *fe2) { | 
					
						
							|  |  |  | 	t := e.t | 
					
						
							|  |  |  | 	double(t[0], &a[0]) | 
					
						
							|  |  |  | 	double(t[1], &a[1]) | 
					
						
							|  |  |  | 	doubleAssign(t[0]) | 
					
						
							|  |  |  | 	doubleAssign(t[1]) | 
					
						
							|  |  |  | 	sub(&c[0], t[0], t[1]) | 
					
						
							|  |  |  | 	add(&c[1], t[0], t[1]) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (e *fp2) inverse(c, a *fe2) { | 
					
						
							|  |  |  | 	t := e.t | 
					
						
							|  |  |  | 	square(t[0], &a[0]) | 
					
						
							|  |  |  | 	square(t[1], &a[1]) | 
					
						
							|  |  |  | 	addAssign(t[0], t[1]) | 
					
						
							|  |  |  | 	inverse(t[0], t[0]) | 
					
						
							|  |  |  | 	mul(&c[0], &a[0], t[0]) | 
					
						
							|  |  |  | 	mul(t[0], t[0], &a[1]) | 
					
						
							|  |  |  | 	neg(&c[1], t[0]) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (e *fp2) mulByFq(c, a *fe2, b *fe) { | 
					
						
							|  |  |  | 	mul(&c[0], &a[0], b) | 
					
						
							|  |  |  | 	mul(&c[1], &a[1], b) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (e *fp2) exp(c, a *fe2, s *big.Int) { | 
					
						
							|  |  |  | 	z := e.one() | 
					
						
							|  |  |  | 	for i := s.BitLen() - 1; i >= 0; i-- { | 
					
						
							|  |  |  | 		e.square(z, z) | 
					
						
							|  |  |  | 		if s.Bit(i) == 1 { | 
					
						
							|  |  |  | 			e.mul(z, z, a) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	c.set(z) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-11 04:25:32 +08:00
										 |  |  | func (e *fp2) frobeniusMap(c, a *fe2, power uint) { | 
					
						
							| 
									
										
											  
											
												core/vm, crypto/bls12381, params: add bls12-381 elliptic curve precompiles (#21018)
* crypto: add bls12-381 elliptic curve wrapper
* params: add bls12-381 precompile gas parameters
* core/vm: add bls12-381 precompiles
* core/vm: add bls12-381 precompile tests
* go.mod, go.sum: use latest bls12381 lib
* core/vm: move point encode/decode functions to base library
* crypto/bls12381: introduce bls12-381 library init function
* crypto/bls12381: import bls12381 elliptic curve implementation
* go.mod, go.sum: remove bls12-381 library
* remove unsued frobenious coeffs
supress warning for inp that used in asm
* add mappings tests for zero inputs
fix swu g2 minus z inverse constant
* crypto/bls12381: fix typo
* crypto/bls12381: better comments for bls12381 constants
* crypto/bls12381: swu, use single conditional for e2
* crypto/bls12381: utils, delete empty line
* crypto/bls12381: utils, use FromHex for string to big
* crypto/bls12381: g1, g2, strict length check for FromBytes
* crypto/bls12381: field_element, comparision changes
* crypto/bls12381: change swu, isogeny constants with hex values
* core/vm: fix point multiplication comments
* core/vm: fix multiexp gas calculation and lookup for g1 and g2
* core/vm: simpler imput length check for multiexp and pairing precompiles
* core/vm: rm empty multiexp result declarations
* crypto/bls12381: remove modulus type definition
* crypto/bls12381: use proper init function
* crypto/bls12381: get rid of new lines at fatal desciprtions
* crypto/bls12-381: fix no-adx assembly multiplication
* crypto/bls12-381: remove old config function
* crypto/bls12381: update multiplication backend
this commit changes mul backend to 6limb eip1962 backend
mul assign operations are dropped
* core/vm/contracts_tests: externalize test vectors for precompiles
* core/vm/contracts_test: externalize failure-cases for precompiles
* core/vm: linting
* go.mod: tiny up sum file
* core/vm: fix goimports linter issues
* crypto/bls12381: build tags for plain ASM or ADX implementation
Co-authored-by: Martin Holst Swende <martin@swende.se>
Co-authored-by: Péter Szilágyi <peterke@gmail.com>
											
										 
											2020-06-03 09:44:32 +03:00
										 |  |  | 	c[0].set(&a[0]) | 
					
						
							|  |  |  | 	if power%2 == 1 { | 
					
						
							|  |  |  | 		neg(&c[1], &a[1]) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	c[1].set(&a[1]) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-11 04:25:32 +08:00
										 |  |  | func (e *fp2) frobeniusMapAssign(a *fe2, power uint) { | 
					
						
							| 
									
										
											  
											
												core/vm, crypto/bls12381, params: add bls12-381 elliptic curve precompiles (#21018)
* crypto: add bls12-381 elliptic curve wrapper
* params: add bls12-381 precompile gas parameters
* core/vm: add bls12-381 precompiles
* core/vm: add bls12-381 precompile tests
* go.mod, go.sum: use latest bls12381 lib
* core/vm: move point encode/decode functions to base library
* crypto/bls12381: introduce bls12-381 library init function
* crypto/bls12381: import bls12381 elliptic curve implementation
* go.mod, go.sum: remove bls12-381 library
* remove unsued frobenious coeffs
supress warning for inp that used in asm
* add mappings tests for zero inputs
fix swu g2 minus z inverse constant
* crypto/bls12381: fix typo
* crypto/bls12381: better comments for bls12381 constants
* crypto/bls12381: swu, use single conditional for e2
* crypto/bls12381: utils, delete empty line
* crypto/bls12381: utils, use FromHex for string to big
* crypto/bls12381: g1, g2, strict length check for FromBytes
* crypto/bls12381: field_element, comparision changes
* crypto/bls12381: change swu, isogeny constants with hex values
* core/vm: fix point multiplication comments
* core/vm: fix multiexp gas calculation and lookup for g1 and g2
* core/vm: simpler imput length check for multiexp and pairing precompiles
* core/vm: rm empty multiexp result declarations
* crypto/bls12381: remove modulus type definition
* crypto/bls12381: use proper init function
* crypto/bls12381: get rid of new lines at fatal desciprtions
* crypto/bls12-381: fix no-adx assembly multiplication
* crypto/bls12-381: remove old config function
* crypto/bls12381: update multiplication backend
this commit changes mul backend to 6limb eip1962 backend
mul assign operations are dropped
* core/vm/contracts_tests: externalize test vectors for precompiles
* core/vm/contracts_test: externalize failure-cases for precompiles
* core/vm: linting
* go.mod: tiny up sum file
* core/vm: fix goimports linter issues
* crypto/bls12381: build tags for plain ASM or ADX implementation
Co-authored-by: Martin Holst Swende <martin@swende.se>
Co-authored-by: Péter Szilágyi <peterke@gmail.com>
											
										 
											2020-06-03 09:44:32 +03:00
										 |  |  | 	if power%2 == 1 { | 
					
						
							|  |  |  | 		neg(&a[1], &a[1]) | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (e *fp2) sqrt(c, a *fe2) bool { | 
					
						
							|  |  |  | 	u, x0, a1, alpha := &fe2{}, &fe2{}, &fe2{}, &fe2{} | 
					
						
							|  |  |  | 	u.set(a) | 
					
						
							|  |  |  | 	e.exp(a1, a, pMinus3Over4) | 
					
						
							|  |  |  | 	e.square(alpha, a1) | 
					
						
							|  |  |  | 	e.mul(alpha, alpha, a) | 
					
						
							|  |  |  | 	e.mul(x0, a1, a) | 
					
						
							|  |  |  | 	if alpha.equal(negativeOne2) { | 
					
						
							|  |  |  | 		neg(&c[0], &x0[1]) | 
					
						
							|  |  |  | 		c[1].set(&x0[0]) | 
					
						
							|  |  |  | 		return true | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	e.add(alpha, alpha, e.one()) | 
					
						
							|  |  |  | 	e.exp(alpha, alpha, pMinus1Over2) | 
					
						
							|  |  |  | 	e.mul(c, alpha, x0) | 
					
						
							|  |  |  | 	e.square(alpha, c) | 
					
						
							|  |  |  | 	return alpha.equal(u) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (e *fp2) isQuadraticNonResidue(a *fe2) bool { | 
					
						
							|  |  |  | 	// https://github.com/leovt/constructible/wiki/Taking-Square-Roots-in-quadratic-extension-Fields | 
					
						
							|  |  |  | 	c0, c1 := new(fe), new(fe) | 
					
						
							|  |  |  | 	square(c0, &a[0]) | 
					
						
							|  |  |  | 	square(c1, &a[1]) | 
					
						
							|  |  |  | 	add(c1, c1, c0) | 
					
						
							|  |  |  | 	return isQuadraticNonResidue(c1) | 
					
						
							|  |  |  | } |