secp256k1: Optimize pubkey parse.

This modifies the ParsePubKey function to avoid an additional
unnecessary check if the point is on the curve in the compressed pubkey
case because it necessarily has already determined if that is true via
the point decompression from the x coordinate.

Also, prevent x from escaping to the heap for the error print in
compressed case while here.

benchmark                          old ns/op    new ns/op   delta
------------------------------------------------------------------
BenchmarkParsePubKeyCompressed     11901        11745       -1.31%
BenchmarkParsePubKeyUncompressed   335          325         -2.99%

benchmark                          old allocs   new allocs  delta
-------------------------------------------------------------------
BenchmarkParsePubKeyCompressed     2            1           -50.00%
BenchmarkParsePubKeyUncompressed   2            1           -50.00%

benchmark                          old bytes    new bytes   delta
-------------------------------------------------------------------
BenchmarkParsePubKeyCompressed     128          80          -37.50%
BenchmarkParsePubKeyUncompressed   128          80          -37.50%
This commit is contained in:
Dave Collins 2020-04-08 14:59:21 -05:00
parent f5800f367f
commit 71f06fbd45
No known key found for this signature in database
GPG Key ID: B8904D9D9C93D1F2

View File

@ -138,6 +138,13 @@ func ParsePubKey(serialized []byte) (key *PublicKey, err error) {
}
}
// Reject public keys that are not on the secp256k1 curve.
if !isOnCurve(&x, &y) {
str := fmt.Sprintf("invalid public key: [%v,%v] not on secp256k1 "+
"curve", x, y)
return nil, makeError(ErrPubKeyNotOnCurve, str)
}
case PubKeyBytesLenCompressed:
// Reject unsupported public key formats for the given length.
format := serialized[0]
@ -162,7 +169,7 @@ func ParsePubKey(serialized []byte) (key *PublicKey, err error) {
wantOddY := format == PubKeyFormatCompressedOdd
if !DecompressY(&x, wantOddY, &y) {
str := fmt.Sprintf("invalid public key: x coordinate %v is not on "+
"the secp256k1 curve", &x)
"the secp256k1 curve", x)
return nil, makeError(ErrPubKeyNotOnCurve, str)
}
y.Normalize()
@ -173,13 +180,6 @@ func ParsePubKey(serialized []byte) (key *PublicKey, err error) {
return nil, makeError(ErrPubKeyInvalidLen, str)
}
// Reject public keys that are not on the secp256k1 curve.
if !isOnCurve(&x, &y) {
str := fmt.Sprintf("invalid public key: [%v,%v] not on secp256k1 curve",
x, y)
return nil, makeError(ErrPubKeyNotOnCurve, str)
}
return NewPublicKey(&x, &y), nil
}