package secp256k1 import ( "math/big" "testing" ) func TestGeneratorIsOnCurve(t *testing.T) { if !G.IsOnCurve() { t.Error("generator point G should be on the curve") } } func TestInfinityIsOnCurve(t *testing.T) { inf := Infinity() if !inf.IsOnCurve() { t.Error("point at infinity should be considered on curve") } } func TestPointNotOnCurve(t *testing.T) { // (1, 1) is not on y² = x³ + 7 // y² = 1, x³ + 7 = 8, so 1 ≠ 8 x := NewFieldElementFromInt64(1) y := NewFieldElementFromInt64(1) _, err := NewPoint(x, y) if err == nil { t.Error("(1, 1) should not be on the curve") } } func TestAddInfinity(t *testing.T) { inf := Infinity() // G + infinity = G result := G.Add(inf) if !result.Equal(G) { t.Error("G + infinity should equal G") } // infinity + G = G result = inf.Add(G) if !result.Equal(G) { t.Error("infinity + G should equal G") } // infinity + infinity = infinity result = inf.Add(inf) if !result.IsInfinity() { t.Error("infinity + infinity should be infinity") } } func TestAddInverseGivesInfinity(t *testing.T) { // G + (-G) = infinity negG := G.Negate() result := G.Add(negG) if !result.IsInfinity() { t.Error("G + (-G) should be infinity") } } func TestDoubleGenerator(t *testing.T) { // 2G should be on the curve twoG := G.Double() if !twoG.IsOnCurve() { t.Error("2G should be on the curve") } // 2G should not be infinity if twoG.IsInfinity() { t.Error("2G should not be infinity") } // 2G should not equal G if twoG.Equal(G) { t.Error("2G should not equal G") } } func TestAddEqualsDouble(t *testing.T) { // G + G should equal G.Double() sum := G.Add(G) doubled := G.Double() if !sum.Equal(doubled) { t.Error("G + G should equal 2G") } } func TestScalarMulByOne(t *testing.T) { // 1 * G = G one := big.NewInt(1) result := G.ScalarMul(one) if !result.Equal(G) { t.Error("1 * G should equal G") } } func TestScalarMulByTwo(t *testing.T) { // 2 * G = G + G two := big.NewInt(2) result := G.ScalarMul(two) expected := G.Double() if !result.Equal(expected) { t.Error("2 * G should equal G.Double()") } } func TestScalarMulByThree(t *testing.T) { // 3 * G = G + G + G three := big.NewInt(3) result := G.ScalarMul(three) expected := G.Double().Add(G) if !result.Equal(expected) { t.Error("3 * G should equal 2G + G") } // Result should be on curve if !result.IsOnCurve() { t.Error("3G should be on the curve") } } func TestScalarMulByN(t *testing.T) { // N * G = infinity (curve order) result := G.ScalarMul(N) if !result.IsInfinity() { t.Error("N * G should be infinity (curve order)") } } func TestScalarMulAssociative(t *testing.T) { // (a * b) * G = a * (b * G) a := big.NewInt(7) b := big.NewInt(11) ab := new(big.Int).Mul(a, b) // 77 left := G.ScalarMul(ab) right := G.ScalarMul(b).ScalarMul(a) if !left.Equal(right) { t.Error("scalar multiplication should be associative") } } func TestNegateOnCurve(t *testing.T) { negG := G.Negate() if !negG.IsOnCurve() { t.Error("-G should be on the curve") } } func TestDoubleNegateEqualsOriginal(t *testing.T) { // -(-G) = G result := G.Negate().Negate() if !result.Equal(G) { t.Error("-(-G) should equal G") } } func TestPointEquality(t *testing.T) { // Same point should be equal if !G.Equal(G) { t.Error("G should equal itself") } // Different points should not be equal twoG := G.Double() if G.Equal(twoG) { t.Error("G should not equal 2G") } // Infinity equals infinity inf1 := Infinity() inf2 := Infinity() if !inf1.Equal(inf2) { t.Error("infinity should equal infinity") } } // Known test vector from Bitcoin func TestKnownVector2G(t *testing.T) { // 2G has known coordinates (verified against bitcoin wiki) expectedX, _ := new(big.Int).SetString("C6047F9441ED7D6D3045406E95C07CD85C778E4B8CEF3CA7ABAC09B95C709EE5", 16) expectedY, _ := new(big.Int).SetString("1AE168FEA63DC339A3C58419466CEAEEF7F632653266D0E1236431A950CFE52A", 16) twoG := G.Double() if twoG.x.value.Cmp(expectedX) != 0 { t.Errorf("2G.x = %s, want %x", twoG.x.String(), expectedX) } if twoG.y.value.Cmp(expectedY) != 0 { t.Errorf("2G.y = %s, want %x", twoG.y.String(), expectedY) } }