* 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>
		
			
				
	
	
		
			252 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			252 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package bls12381
 | 
						|
 | 
						|
import (
 | 
						|
	"bytes"
 | 
						|
	"crypto/rand"
 | 
						|
	"math/big"
 | 
						|
	"testing"
 | 
						|
)
 | 
						|
 | 
						|
func TestFieldElementValidation(t *testing.T) {
 | 
						|
	zero := new(fe).zero()
 | 
						|
	if !zero.isValid() {
 | 
						|
		t.Fatal("zero must be valid")
 | 
						|
	}
 | 
						|
	one := new(fe).one()
 | 
						|
	if !one.isValid() {
 | 
						|
		t.Fatal("one must be valid")
 | 
						|
	}
 | 
						|
	if modulus.isValid() {
 | 
						|
		t.Fatal("modulus must be invalid")
 | 
						|
	}
 | 
						|
	n := modulus.big()
 | 
						|
	n.Add(n, big.NewInt(1))
 | 
						|
	if new(fe).setBig(n).isValid() {
 | 
						|
		t.Fatal("number greater than modulus must be invalid")
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestFieldElementEquality(t *testing.T) {
 | 
						|
	// fe
 | 
						|
	zero := new(fe).zero()
 | 
						|
	if !zero.equal(zero) {
 | 
						|
		t.Fatal("0 == 0")
 | 
						|
	}
 | 
						|
	one := new(fe).one()
 | 
						|
	if !one.equal(one) {
 | 
						|
		t.Fatal("1 == 1")
 | 
						|
	}
 | 
						|
	a, _ := new(fe).rand(rand.Reader)
 | 
						|
	if !a.equal(a) {
 | 
						|
		t.Fatal("a == a")
 | 
						|
	}
 | 
						|
	b := new(fe)
 | 
						|
	add(b, a, one)
 | 
						|
	if a.equal(b) {
 | 
						|
		t.Fatal("a != a + 1")
 | 
						|
	}
 | 
						|
	// fe2
 | 
						|
	zero2 := new(fe2).zero()
 | 
						|
	if !zero2.equal(zero2) {
 | 
						|
		t.Fatal("0 == 0")
 | 
						|
	}
 | 
						|
	one2 := new(fe2).one()
 | 
						|
	if !one2.equal(one2) {
 | 
						|
		t.Fatal("1 == 1")
 | 
						|
	}
 | 
						|
	a2, _ := new(fe2).rand(rand.Reader)
 | 
						|
	if !a2.equal(a2) {
 | 
						|
		t.Fatal("a == a")
 | 
						|
	}
 | 
						|
	b2 := new(fe2)
 | 
						|
	fp2 := newFp2()
 | 
						|
	fp2.add(b2, a2, one2)
 | 
						|
	if a2.equal(b2) {
 | 
						|
		t.Fatal("a != a + 1")
 | 
						|
	}
 | 
						|
	// fe6
 | 
						|
	zero6 := new(fe6).zero()
 | 
						|
	if !zero6.equal(zero6) {
 | 
						|
		t.Fatal("0 == 0")
 | 
						|
	}
 | 
						|
	one6 := new(fe6).one()
 | 
						|
	if !one6.equal(one6) {
 | 
						|
		t.Fatal("1 == 1")
 | 
						|
	}
 | 
						|
	a6, _ := new(fe6).rand(rand.Reader)
 | 
						|
	if !a6.equal(a6) {
 | 
						|
		t.Fatal("a == a")
 | 
						|
	}
 | 
						|
	b6 := new(fe6)
 | 
						|
	fp6 := newFp6(fp2)
 | 
						|
	fp6.add(b6, a6, one6)
 | 
						|
	if a6.equal(b6) {
 | 
						|
		t.Fatal("a != a + 1")
 | 
						|
	}
 | 
						|
	// fe12
 | 
						|
	zero12 := new(fe12).zero()
 | 
						|
	if !zero12.equal(zero12) {
 | 
						|
		t.Fatal("0 == 0")
 | 
						|
	}
 | 
						|
	one12 := new(fe12).one()
 | 
						|
	if !one12.equal(one12) {
 | 
						|
		t.Fatal("1 == 1")
 | 
						|
	}
 | 
						|
	a12, _ := new(fe12).rand(rand.Reader)
 | 
						|
	if !a12.equal(a12) {
 | 
						|
		t.Fatal("a == a")
 | 
						|
	}
 | 
						|
	b12 := new(fe12)
 | 
						|
	fp12 := newFp12(fp6)
 | 
						|
	fp12.add(b12, a12, one12)
 | 
						|
	if a12.equal(b12) {
 | 
						|
		t.Fatal("a != a + 1")
 | 
						|
	}
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
func TestFieldElementHelpers(t *testing.T) {
 | 
						|
	// fe
 | 
						|
	zero := new(fe).zero()
 | 
						|
	if !zero.isZero() {
 | 
						|
		t.Fatal("'zero' is not zero")
 | 
						|
	}
 | 
						|
	one := new(fe).one()
 | 
						|
	if !one.isOne() {
 | 
						|
		t.Fatal("'one' is not one")
 | 
						|
	}
 | 
						|
	odd := new(fe).setBig(big.NewInt(1))
 | 
						|
	if !odd.isOdd() {
 | 
						|
		t.Fatal("1 must be odd")
 | 
						|
	}
 | 
						|
	if odd.isEven() {
 | 
						|
		t.Fatal("1 must not be even")
 | 
						|
	}
 | 
						|
	even := new(fe).setBig(big.NewInt(2))
 | 
						|
	if !even.isEven() {
 | 
						|
		t.Fatal("2 must be even")
 | 
						|
	}
 | 
						|
	if even.isOdd() {
 | 
						|
		t.Fatal("2 must not be odd")
 | 
						|
	}
 | 
						|
	// fe2
 | 
						|
	zero2 := new(fe2).zero()
 | 
						|
	if !zero2.isZero() {
 | 
						|
		t.Fatal("'zero' is not zero, 2")
 | 
						|
	}
 | 
						|
	one2 := new(fe2).one()
 | 
						|
	if !one2.isOne() {
 | 
						|
		t.Fatal("'one' is not one, 2")
 | 
						|
	}
 | 
						|
	// fe6
 | 
						|
	zero6 := new(fe6).zero()
 | 
						|
	if !zero6.isZero() {
 | 
						|
		t.Fatal("'zero' is not zero, 6")
 | 
						|
	}
 | 
						|
	one6 := new(fe6).one()
 | 
						|
	if !one6.isOne() {
 | 
						|
		t.Fatal("'one' is not one, 6")
 | 
						|
	}
 | 
						|
	// fe12
 | 
						|
	zero12 := new(fe12).zero()
 | 
						|
	if !zero12.isZero() {
 | 
						|
		t.Fatal("'zero' is not zero, 12")
 | 
						|
	}
 | 
						|
	one12 := new(fe12).one()
 | 
						|
	if !one12.isOne() {
 | 
						|
		t.Fatal("'one' is not one, 12")
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestFieldElementSerialization(t *testing.T) {
 | 
						|
	t.Run("zero", func(t *testing.T) {
 | 
						|
		in := make([]byte, 48)
 | 
						|
		fe := new(fe).setBytes(in)
 | 
						|
		if !fe.isZero() {
 | 
						|
			t.Fatal("bad serialization")
 | 
						|
		}
 | 
						|
		if !bytes.Equal(in, fe.bytes()) {
 | 
						|
			t.Fatal("bad serialization")
 | 
						|
		}
 | 
						|
	})
 | 
						|
	t.Run("bytes", func(t *testing.T) {
 | 
						|
		for i := 0; i < fuz; i++ {
 | 
						|
			a, _ := new(fe).rand(rand.Reader)
 | 
						|
			b := new(fe).setBytes(a.bytes())
 | 
						|
			if !a.equal(b) {
 | 
						|
				t.Fatal("bad serialization")
 | 
						|
			}
 | 
						|
		}
 | 
						|
	})
 | 
						|
	t.Run("big", func(t *testing.T) {
 | 
						|
		for i := 0; i < fuz; i++ {
 | 
						|
			a, _ := new(fe).rand(rand.Reader)
 | 
						|
			b := new(fe).setBig(a.big())
 | 
						|
			if !a.equal(b) {
 | 
						|
				t.Fatal("bad encoding or decoding")
 | 
						|
			}
 | 
						|
		}
 | 
						|
	})
 | 
						|
	t.Run("string", func(t *testing.T) {
 | 
						|
		for i := 0; i < fuz; i++ {
 | 
						|
			a, _ := new(fe).rand(rand.Reader)
 | 
						|
			b, err := new(fe).setString(a.string())
 | 
						|
			if err != nil {
 | 
						|
				t.Fatal(err)
 | 
						|
			}
 | 
						|
			if !a.equal(b) {
 | 
						|
				t.Fatal("bad encoding or decoding")
 | 
						|
			}
 | 
						|
		}
 | 
						|
	})
 | 
						|
}
 | 
						|
 | 
						|
func TestFieldElementByteInputs(t *testing.T) {
 | 
						|
	zero := new(fe).zero()
 | 
						|
	in := make([]byte, 0)
 | 
						|
	a := new(fe).setBytes(in)
 | 
						|
	if !a.equal(zero) {
 | 
						|
		t.Fatal("bad serialization")
 | 
						|
	}
 | 
						|
	in = make([]byte, 48)
 | 
						|
	a = new(fe).setBytes(in)
 | 
						|
	if !a.equal(zero) {
 | 
						|
		t.Fatal("bad serialization")
 | 
						|
	}
 | 
						|
	in = make([]byte, 64)
 | 
						|
	a = new(fe).setBytes(in)
 | 
						|
	if !a.equal(zero) {
 | 
						|
		t.Fatal("bad serialization")
 | 
						|
	}
 | 
						|
	in = make([]byte, 49)
 | 
						|
	in[47] = 1
 | 
						|
	normalOne := &fe{1, 0, 0, 0, 0, 0}
 | 
						|
	a = new(fe).setBytes(in)
 | 
						|
	if !a.equal(normalOne) {
 | 
						|
		t.Fatal("bad serialization")
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestFieldElementCopy(t *testing.T) {
 | 
						|
	a, _ := new(fe).rand(rand.Reader)
 | 
						|
	b := new(fe).set(a)
 | 
						|
	if !a.equal(b) {
 | 
						|
		t.Fatal("bad copy, 1")
 | 
						|
	}
 | 
						|
	a2, _ := new(fe2).rand(rand.Reader)
 | 
						|
	b2 := new(fe2).set(a2)
 | 
						|
	if !a2.equal(b2) {
 | 
						|
		t.Fatal("bad copy, 2")
 | 
						|
	}
 | 
						|
	a6, _ := new(fe6).rand(rand.Reader)
 | 
						|
	b6 := new(fe6).set(a6)
 | 
						|
	if !a6.equal(b6) {
 | 
						|
		t.Fatal("bad copy, 6")
 | 
						|
	}
 | 
						|
	a12, _ := new(fe12).rand(rand.Reader)
 | 
						|
	b12 := new(fe12).set(a12)
 | 
						|
	if !a12.equal(b12) {
 | 
						|
		t.Fatal("bad copy, 12")
 | 
						|
	}
 | 
						|
}
 |