package main

import (
	"crypto/rand"
	"fmt"
	"math/big"
	"sync"

	"xdx.jelly/xgcl/sm/sm2"
	"xdx.jelly/xgcl/sm/sm2/ec256"
)

func assertEqual(a, b interface{}) {
	switch a.(type) {
	case *big.Int:
		if a.(*big.Int).Cmp(b.(*big.Int)) != 0 {
			panic("assert equal failed")
		}
	case []uint64:
		aa := a.([]uint64)
		bb := b.([]uint64)
		for i := 0; i < len(aa); i++ {
			if aa[i] != bb[i] {
				panic("assert equal failed")
			}
		}
	default:
		panic("unknown type")
	}
}

var param = sm2.Curve().Params()
var c256 = sm2.Curve().(ec256.SM2CurveParam)

func testScalarMult() {
	for i := 0; i < 1000; i++ {
		k, _ := rand.Int(rand.Reader, param.N)

		x1, y1 := param.ScalarMult(param.Gx, param.Gy, k.Bytes())
		x2, y2 := c256.CurveParams.ScalarMult(param.Gx, param.Gy, k.Bytes())

		assertEqual(x1, x2)
		assertEqual(y1, y2)
	}
}

func testScalarBaseMult() {
	for i := 0; i < 1000; i++ {
		k, _ := rand.Int(rand.Reader, param.N)
		x1, y1 := param.ScalarBaseMult(k.Bytes())
		x2, y2 := c256.CurveParams.ScalarBaseMult(k.Bytes())

		assertEqual(x1, x2)
		assertEqual(y1, y2)
	}
}

func main() {
	n := 10000000
	var wg sync.WaitGroup
	wg.Add(2)
	go func() {
		for i := 0; i < n; i++ {
			if i%10 == 0 {
				fmt.Printf("testScalarBaseMult - %d\n", 1000*i)
			}
			testScalarBaseMult()
		}
		wg.Done()
	}()
	go func() {
		for i := 0; i < n; i++ {
			if i%10 == 0 {
				fmt.Printf("testScalarMult - %d\n", 1000*i)
			}
			testScalarMult()
		}
		wg.Done()
	}()
	wg.Wait()
}
