btcd/internal_test.go
Josh Rickmar 1dbf389ceb Optimize public key serialization.
This change removes the internal pad function in favor a more opimized
paddedAppend function.  Unlike pad, which would always alloate a new
slice of the desired size and copy the bytes into it, paddedAppend
only appends the leading padding when necesary, and uses the builtin
append to copy the remaining source bytes.  pad was also used in
combination with another call to the builtin copy func to copy into a
zeroed byte slice.  As the slice is now created using make with an
initial length of zero, this copy can also be removed.

As confirmed by poking the bytes with the unsafe package, gc does not
zero array elements between the len and cap when allocating slices
with make().  In combination with the paddedAppend func, this results
in only a single copy of each byte, with no unnecssary zeroing, when
creating the serialized pubkeys.  This has not been tested with other
Go compilers (namely, gccgo and llgo), but the new behavior is still
functionally correct regardless of compiler optimizations.

The TestPad function has been removed as the pad func it tested has
likewise been removed.

ok @davecgh
2014-05-19 23:13:48 -05:00

72 lines
2.2 KiB
Go

// Copyright (c) 2013-2014 Conformal Systems LLC.
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package btcec
import (
"math/big"
)
const (
TstPubkeyUncompressed = pubkeyUncompressed
TstPubkeyCompressed = pubkeyCompressed
TstPubkeyHybrid = pubkeyHybrid
)
// TstRawInts allows the test package to get the integers from the internal
// field representation for ensuring correctness. It is only available during
// the tests.
func (f *fieldVal) TstRawInts() [10]uint32 {
return f.n
}
// TstSetRawInts allows the test package to directly set the integers used by
// the internal field representation. It is only available during the tests.
func (f *fieldVal) TstSetRawInts(raw [10]uint32) *fieldVal {
for i := 0; i < len(raw); i++ {
f.n[i] = raw[i]
}
return f
}
// TstFieldJacobianToBigAffine makes the internal fieldJacobianToBigAffine
// function available to the test package.
func (curve *KoblitzCurve) TstFieldJacobianToBigAffine(x, y, z *fieldVal) (*big.Int, *big.Int) {
return curve.fieldJacobianToBigAffine(x, y, z)
}
// TstIsJacobianOnCurve returns boolean if the point (x,y,z) is on the curve.
func (curve *KoblitzCurve) TstIsJacobianOnCurve(x, y, z *fieldVal) bool {
// Elliptic curve equation for secp256k1 is: y^2 = x^3 + 7
// In Jacobian coordinates, Y = y/z^3 and X = x/z^2
// Thus:
// (y/z^3)^2 = (x/z^2)^3 + 7
// y^2/z^6 = x^3/z^6 + 7
// y^2 = x^3 + 7*z^6
var y2, z2, x3, result fieldVal
y2.SquareVal(y).Normalize()
z2.SquareVal(z)
x3.SquareVal(x).Mul(x)
result.SquareVal(&z2).Mul(&z2).MulInt(7).Add(&x3).Normalize()
return y2.Equals(&result)
}
// TstAddJacobian makes the internal addJacobian function available to the test
// package.
func (curve *KoblitzCurve) TstAddJacobian(x1, y1, z1, x2, y2, z2, x3, y3, z3 *fieldVal) {
curve.addJacobian(x1, y1, z1, x2, y2, z2, x3, y3, z3)
}
// TstDoubleJacobian makes the internal doubleJacobian function available to the test
// package.
func (curve *KoblitzCurve) TstDoubleJacobian(x1, y1, z1, x3, y3, z3 *fieldVal) {
curve.doubleJacobian(x1, y1, z1, x3, y3, z3)
}
// NewFieldVal returns a new field value set to 0. This is only available to
// the test package.
func NewFieldVal() *fieldVal {
return new(fieldVal)
}