Remove deprecated files and update README to reflect current implementation status and features. This commit deletes unused context, ecmult, and test files, streamlining the codebase. The README has been revised to include architectural details, performance benchmarks, and security considerations for the secp256k1 implementation.
This commit is contained in:
499
group_test.go
Normal file
499
group_test.go
Normal file
@@ -0,0 +1,499 @@
|
||||
package p256k1
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGroupElementBasics(t *testing.T) {
|
||||
// Test infinity point
|
||||
var inf GroupElementAffine
|
||||
inf.setInfinity()
|
||||
if !inf.isInfinity() {
|
||||
t.Error("Infinity point should be infinity")
|
||||
}
|
||||
|
||||
// Test generator point
|
||||
gen := GeneratorAffine
|
||||
if gen.isInfinity() {
|
||||
t.Error("Generator should not be infinity")
|
||||
}
|
||||
|
||||
// Test validity
|
||||
if !gen.isValid() {
|
||||
t.Error("Generator should be valid")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGroupElementNegation(t *testing.T) {
|
||||
// Test negation of generator
|
||||
gen := GeneratorAffine
|
||||
var negGen GroupElementAffine
|
||||
negGen.negate(&gen)
|
||||
|
||||
if negGen.isInfinity() {
|
||||
t.Error("Negation of generator should not be infinity")
|
||||
}
|
||||
|
||||
// Test double negation
|
||||
var doubleNeg GroupElementAffine
|
||||
doubleNeg.negate(&negGen)
|
||||
|
||||
if !doubleNeg.equal(&gen) {
|
||||
t.Error("Double negation should return original point")
|
||||
}
|
||||
|
||||
// Test negation of infinity
|
||||
var inf, negInf GroupElementAffine
|
||||
inf.setInfinity()
|
||||
negInf.negate(&inf)
|
||||
|
||||
if !negInf.isInfinity() {
|
||||
t.Error("Negation of infinity should be infinity")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGroupElementSetXY(t *testing.T) {
|
||||
// Test setting coordinates
|
||||
var point GroupElementAffine
|
||||
var x, y FieldElement
|
||||
x.setInt(1)
|
||||
y.setInt(1)
|
||||
|
||||
point.setXY(&x, &y)
|
||||
|
||||
if point.isInfinity() {
|
||||
t.Error("Point with coordinates should not be infinity")
|
||||
}
|
||||
|
||||
// Test that coordinates are preserved
|
||||
if !point.x.equal(&x) {
|
||||
t.Error("X coordinate should be preserved")
|
||||
}
|
||||
if !point.y.equal(&y) {
|
||||
t.Error("Y coordinate should be preserved")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGroupElementSetXOVar(t *testing.T) {
|
||||
// Test setting from X coordinate and oddness
|
||||
var x FieldElement
|
||||
x.setInt(1) // This may not be on the curve, but test the function
|
||||
|
||||
var point GroupElementAffine
|
||||
// Try both odd and even Y
|
||||
success := point.setXOVar(&x, false)
|
||||
if success && point.isInfinity() {
|
||||
t.Error("Successfully created point should not be infinity")
|
||||
}
|
||||
|
||||
success = point.setXOVar(&x, true)
|
||||
if success && point.isInfinity() {
|
||||
t.Error("Successfully created point should not be infinity")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGroupElementEquality(t *testing.T) {
|
||||
// Test equality with same point
|
||||
gen := GeneratorAffine
|
||||
var gen2 GroupElementAffine
|
||||
gen2 = gen
|
||||
|
||||
if !gen.equal(&gen2) {
|
||||
t.Error("Same points should be equal")
|
||||
}
|
||||
|
||||
// Test inequality with different points
|
||||
var negGen GroupElementAffine
|
||||
negGen.negate(&gen)
|
||||
|
||||
if gen.equal(&negGen) {
|
||||
t.Error("Generator and its negation should not be equal")
|
||||
}
|
||||
|
||||
// Test equality of infinity points
|
||||
var inf1, inf2 GroupElementAffine
|
||||
inf1.setInfinity()
|
||||
inf2.setInfinity()
|
||||
|
||||
if !inf1.equal(&inf2) {
|
||||
t.Error("Two infinity points should be equal")
|
||||
}
|
||||
|
||||
// Test inequality between infinity and non-infinity
|
||||
if gen.equal(&inf1) {
|
||||
t.Error("Generator and infinity should not be equal")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGroupElementJacobianBasics(t *testing.T) {
|
||||
// Test infinity
|
||||
var inf GroupElementJacobian
|
||||
inf.setInfinity()
|
||||
if !inf.isInfinity() {
|
||||
t.Error("Jacobian infinity should be infinity")
|
||||
}
|
||||
|
||||
// Test conversion from affine
|
||||
gen := GeneratorAffine
|
||||
var genJ GroupElementJacobian
|
||||
genJ.setGE(&gen)
|
||||
|
||||
if genJ.isInfinity() {
|
||||
t.Error("Jacobian generator should not be infinity")
|
||||
}
|
||||
|
||||
// Test conversion back to affine
|
||||
var genBack GroupElementAffine
|
||||
genBack.setGEJ(&genJ)
|
||||
|
||||
if !genBack.equal(&gen) {
|
||||
t.Error("Round-trip conversion should preserve point")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGroupElementJacobianDoubling(t *testing.T) {
|
||||
// Test point doubling
|
||||
gen := GeneratorAffine
|
||||
var genJ GroupElementJacobian
|
||||
genJ.setGE(&gen)
|
||||
|
||||
var doubled GroupElementJacobian
|
||||
doubled.double(&genJ)
|
||||
|
||||
if doubled.isInfinity() {
|
||||
t.Error("Doubled generator should not be infinity")
|
||||
}
|
||||
|
||||
// Test doubling infinity
|
||||
var inf, doubledInf GroupElementJacobian
|
||||
inf.setInfinity()
|
||||
doubledInf.double(&inf)
|
||||
|
||||
if !doubledInf.isInfinity() {
|
||||
t.Error("Doubled infinity should be infinity")
|
||||
}
|
||||
|
||||
// Test that 2*P != P (for non-zero points)
|
||||
var doubledAffine GroupElementAffine
|
||||
doubledAffine.setGEJ(&doubled)
|
||||
|
||||
if doubledAffine.equal(&gen) {
|
||||
t.Error("2*G should not equal G")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGroupElementJacobianAddition(t *testing.T) {
|
||||
// Test P + O = P (where O is infinity)
|
||||
gen := GeneratorAffine
|
||||
var genJ GroupElementJacobian
|
||||
genJ.setGE(&gen)
|
||||
|
||||
var inf GroupElementJacobian
|
||||
inf.setInfinity()
|
||||
|
||||
var result GroupElementJacobian
|
||||
result.addVar(&genJ, &inf)
|
||||
|
||||
var resultAffine GroupElementAffine
|
||||
resultAffine.setGEJ(&result)
|
||||
|
||||
if !resultAffine.equal(&gen) {
|
||||
t.Error("P + O should equal P")
|
||||
}
|
||||
|
||||
// Test O + P = P
|
||||
result.addVar(&inf, &genJ)
|
||||
resultAffine.setGEJ(&result)
|
||||
|
||||
if !resultAffine.equal(&gen) {
|
||||
t.Error("O + P should equal P")
|
||||
}
|
||||
|
||||
// Test P + (-P) = O
|
||||
var negGen GroupElementAffine
|
||||
negGen.negate(&gen)
|
||||
var negGenJ GroupElementJacobian
|
||||
negGenJ.setGE(&negGen)
|
||||
|
||||
result.addVar(&genJ, &negGenJ)
|
||||
|
||||
if !result.isInfinity() {
|
||||
t.Error("P + (-P) should equal infinity")
|
||||
}
|
||||
|
||||
// Test P + P = 2P (should equal doubling)
|
||||
var sum, doubled GroupElementJacobian
|
||||
sum.addVar(&genJ, &genJ)
|
||||
doubled.double(&genJ)
|
||||
|
||||
var sumAffine, doubledAffine GroupElementAffine
|
||||
sumAffine.setGEJ(&sum)
|
||||
doubledAffine.setGEJ(&doubled)
|
||||
|
||||
if !sumAffine.equal(&doubledAffine) {
|
||||
t.Error("P + P should equal 2*P")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGroupElementAddGE(t *testing.T) {
|
||||
// Test mixed addition (Jacobian + Affine)
|
||||
gen := GeneratorAffine
|
||||
var genJ GroupElementJacobian
|
||||
genJ.setGE(&gen)
|
||||
|
||||
var negGen GroupElementAffine
|
||||
negGen.negate(&gen)
|
||||
|
||||
var result GroupElementJacobian
|
||||
result.addGE(&genJ, &negGen)
|
||||
|
||||
if !result.isInfinity() {
|
||||
t.Error("P + (-P) should equal infinity in mixed addition")
|
||||
}
|
||||
|
||||
// Test adding infinity
|
||||
var inf GroupElementAffine
|
||||
inf.setInfinity()
|
||||
|
||||
result.addGE(&genJ, &inf)
|
||||
var resultAffine GroupElementAffine
|
||||
resultAffine.setGEJ(&result)
|
||||
|
||||
if !resultAffine.equal(&gen) {
|
||||
t.Error("P + O should equal P in mixed addition")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGroupElementNegationJacobian(t *testing.T) {
|
||||
// Test Jacobian negation
|
||||
gen := GeneratorAffine
|
||||
var genJ GroupElementJacobian
|
||||
genJ.setGE(&gen)
|
||||
|
||||
var negGenJ GroupElementJacobian
|
||||
negGenJ.negate(&genJ)
|
||||
|
||||
if negGenJ.isInfinity() {
|
||||
t.Error("Negated Jacobian point should not be infinity")
|
||||
}
|
||||
|
||||
// Convert back to affine and compare
|
||||
var negGenAffine, expectedNegAffine GroupElementAffine
|
||||
negGenAffine.setGEJ(&negGenJ)
|
||||
expectedNegAffine.negate(&gen)
|
||||
|
||||
if !negGenAffine.equal(&expectedNegAffine) {
|
||||
t.Error("Jacobian negation should match affine negation")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGroupElementStorage(t *testing.T) {
|
||||
// Test storage conversion
|
||||
gen := GeneratorAffine
|
||||
var storage GroupElementStorage
|
||||
gen.toStorage(&storage)
|
||||
|
||||
var restored GroupElementAffine
|
||||
restored.fromStorage(&storage)
|
||||
|
||||
if !restored.equal(&gen) {
|
||||
t.Error("Storage round-trip should preserve point")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGroupElementBytes(t *testing.T) {
|
||||
// Test byte conversion
|
||||
gen := GeneratorAffine
|
||||
var bytes [64]byte
|
||||
gen.toBytes(bytes[:])
|
||||
|
||||
var restored GroupElementAffine
|
||||
restored.fromBytes(bytes[:])
|
||||
|
||||
if !restored.equal(&gen) {
|
||||
t.Error("Byte round-trip should preserve point")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGroupElementClear(t *testing.T) {
|
||||
// Test clearing affine point
|
||||
gen := GeneratorAffine
|
||||
gen.clear()
|
||||
|
||||
if !gen.isInfinity() {
|
||||
t.Error("Cleared affine point should be infinity")
|
||||
}
|
||||
|
||||
// Test clearing Jacobian point
|
||||
var genJ GroupElementJacobian
|
||||
genJ.setGE(&GeneratorAffine)
|
||||
genJ.clear()
|
||||
|
||||
if !genJ.isInfinity() {
|
||||
t.Error("Cleared Jacobian point should be infinity")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGroupElementRandomOperations(t *testing.T) {
|
||||
// Test with random scalar multiplications (simplified)
|
||||
gen := GeneratorAffine
|
||||
var genJ GroupElementJacobian
|
||||
genJ.setGE(&gen)
|
||||
|
||||
// Test associativity: (P + P) + P = P + (P + P)
|
||||
var p_plus_p, left, right GroupElementJacobian
|
||||
p_plus_p.addVar(&genJ, &genJ)
|
||||
left.addVar(&p_plus_p, &genJ)
|
||||
right.addVar(&genJ, &p_plus_p)
|
||||
|
||||
var leftAffine, rightAffine GroupElementAffine
|
||||
leftAffine.setGEJ(&left)
|
||||
rightAffine.setGEJ(&right)
|
||||
|
||||
if !leftAffine.equal(&rightAffine) {
|
||||
t.Error("Addition should be associative")
|
||||
}
|
||||
|
||||
// Test commutativity: P + Q = Q + P
|
||||
var doubled GroupElementJacobian
|
||||
doubled.double(&genJ)
|
||||
|
||||
var sum1, sum2 GroupElementJacobian
|
||||
sum1.addVar(&genJ, &doubled)
|
||||
sum2.addVar(&doubled, &genJ)
|
||||
|
||||
var sum1Affine, sum2Affine GroupElementAffine
|
||||
sum1Affine.setGEJ(&sum1)
|
||||
sum2Affine.setGEJ(&sum2)
|
||||
|
||||
if !sum1Affine.equal(&sum2Affine) {
|
||||
t.Error("Addition should be commutative")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGroupElementEdgeCases(t *testing.T) {
|
||||
// Test operations with infinity
|
||||
var inf GroupElementAffine
|
||||
inf.setInfinity()
|
||||
|
||||
// Test negation of infinity
|
||||
var negInf GroupElementAffine
|
||||
negInf.negate(&inf)
|
||||
if !negInf.isInfinity() {
|
||||
t.Error("Negation of infinity should be infinity")
|
||||
}
|
||||
|
||||
// Test setting infinity to coordinates (should remain infinity)
|
||||
var x, y FieldElement
|
||||
x.setInt(0)
|
||||
y.setInt(0)
|
||||
inf.setXY(&x, &y)
|
||||
if inf.isInfinity() {
|
||||
t.Error("Setting coordinates should make point non-infinity")
|
||||
}
|
||||
|
||||
// Reset to infinity for next test
|
||||
inf.setInfinity()
|
||||
|
||||
// Test conversion of infinity to Jacobian
|
||||
var infJ GroupElementJacobian
|
||||
infJ.setGE(&inf)
|
||||
if !infJ.isInfinity() {
|
||||
t.Error("Jacobian conversion of infinity should be infinity")
|
||||
}
|
||||
|
||||
// Test conversion back
|
||||
var infBack GroupElementAffine
|
||||
infBack.setGEJ(&infJ)
|
||||
if !infBack.isInfinity() {
|
||||
t.Error("Affine conversion of Jacobian infinity should be infinity")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGroupElementMultipleDoubling(t *testing.T) {
|
||||
// Test multiple doublings: 2^n * G
|
||||
gen := GeneratorAffine
|
||||
var current GroupElementJacobian
|
||||
current.setGE(&gen)
|
||||
|
||||
var powers [8]GroupElementAffine
|
||||
powers[0] = gen
|
||||
|
||||
// Compute 2^i * G for i = 1..7
|
||||
for i := 1; i < 8; i++ {
|
||||
current.double(¤t)
|
||||
powers[i].setGEJ(¤t)
|
||||
|
||||
if powers[i].isInfinity() {
|
||||
t.Errorf("2^%d * G should not be infinity", i)
|
||||
}
|
||||
|
||||
// Check that each power is different from previous ones
|
||||
for j := 0; j < i; j++ {
|
||||
if powers[i].equal(&powers[j]) {
|
||||
t.Errorf("2^%d * G should not equal 2^%d * G", i, j)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Benchmark tests
|
||||
func BenchmarkGroupElementDouble(b *testing.B) {
|
||||
gen := GeneratorAffine
|
||||
var genJ, result GroupElementJacobian
|
||||
genJ.setGE(&gen)
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
result.double(&genJ)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkGroupElementAddVar(b *testing.B) {
|
||||
gen := GeneratorAffine
|
||||
var genJ, doubled, result GroupElementJacobian
|
||||
genJ.setGE(&gen)
|
||||
doubled.double(&genJ)
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
result.addVar(&genJ, &doubled)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkGroupElementAddGE(b *testing.B) {
|
||||
gen := GeneratorAffine
|
||||
var genJ, result GroupElementJacobian
|
||||
genJ.setGE(&gen)
|
||||
|
||||
var negGen GroupElementAffine
|
||||
negGen.negate(&gen)
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
result.addGE(&genJ, &negGen)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkGroupElementSetGEJ(b *testing.B) {
|
||||
gen := GeneratorAffine
|
||||
var genJ GroupElementJacobian
|
||||
genJ.setGE(&gen)
|
||||
|
||||
var result GroupElementAffine
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
result.setGEJ(&genJ)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkGroupElementNegate(b *testing.B) {
|
||||
gen := GeneratorAffine
|
||||
var result GroupElementAffine
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
result.negate(&gen)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user