This commit is contained in:
ziggieXXX 2025-03-11 10:08:42 +09:00 committed by GitHub
commit 5fda9244ff
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 72 additions and 1 deletions

View file

@ -1,6 +1,8 @@
package btcec package btcec
import secp "github.com/decred/dcrd/dcrec/secp256k1/v4" import (
secp "github.com/decred/dcrd/dcrec/secp256k1/v4"
)
// FieldVal implements optimized fixed-precision arithmetic over the secp256k1 // FieldVal implements optimized fixed-precision arithmetic over the secp256k1
// finite field. This means all arithmetic is performed modulo // finite field. This means all arithmetic is performed modulo

View file

@ -52,6 +52,15 @@ func NewPublicKey(x, y *FieldVal) *PublicKey {
return secp.NewPublicKey(x, y) return secp.NewPublicKey(x, y)
} }
// CopyPublicKey returns a deep copy of the public key.
func CopyPublicKey(pk *PublicKey) *PublicKey {
var result secp.JacobianPoint
pk.AsJacobian(&result)
result.ToAffine()
return NewPublicKey(&result.X, &result.Y)
}
// SerializedKey is a type for representing a public key in its compressed // SerializedKey is a type for representing a public key in its compressed
// serialized form. // serialized form.
// //

View file

@ -6,7 +6,9 @@ package btcec
import ( import (
"bytes" "bytes"
"math/rand"
"testing" "testing"
"testing/quick"
"github.com/davecgh/go-spew/spew" "github.com/davecgh/go-spew/spew"
) )
@ -292,3 +294,61 @@ func TestIsCompressed(t *testing.T) {
} }
} }
} }
// TestCopyPublicKeyProperties tests that the CopyPublicKey function deep
// copies the original public key and that the copy is equal to the original.
func TestCopyPublicKeyProperties(t *testing.T) {
f := func(x, y [32]byte) bool {
// Convert byte slices to FieldVals.
xf := new(FieldVal)
yf := new(FieldVal)
if overflow := xf.SetByteSlice(x[:]); overflow {
// Only check the function for valid coordinates.
return true
}
if overflow := xf.SetByteSlice(y[:]); overflow {
// Only check the function for valid coordinates.
return true
}
// Create an original public key.
original := NewPublicKey(xf, yf)
if original == nil {
// Skip invalid inputs.
return true
}
// Make a copy of the original public key.
copied := CopyPublicKey(original)
if copied == nil {
// copy should succeed if original was valid.
return false
}
// The copy should not be the same instance.
if original == copied {
return false
}
// The copy should be equal to the original
// First check the serialized forms.
originalBytes := original.SerializeCompressed()
copiedBytes := copied.SerializeCompressed()
if !bytes.Equal(originalBytes, copiedBytes) {
return false
}
return original.IsEqual(copied)
}
// Create a deterministic random source using a fixed seed.
rng := rand.New(rand.NewSource(42))
config := &quick.Config{
Rand: rng,
}
if err := quick.Check(f, config); err != nil {
t.Error(err)
}
}