d69442834c
Code uses a windowing/precomputing strategy to minimize ECC math. Every 8-bit window of the 256 bits that compose a possible scalar multiple has a complete map that's pre-computed. The precomputed data is in secp256k1.go and the generator for that file is in gensecp256k1.go Also fixed a spelling error in a benchmark test. Results so far seem to indicate the time taken is about 35% of what it was before. Closes #2
66 lines
2.7 KiB
Go
66 lines
2.7 KiB
Go
// Copyright (c) 2014 Conformal Systems LLC.
|
|
// Use of this source code is governed by an ISC
|
|
// license that can be found in the LICENSE file.
|
|
// +build gensecp256k1
|
|
|
|
package btcec
|
|
|
|
import (
|
|
"fmt"
|
|
)
|
|
|
|
// getDoublingPoints returns all the possible G^(2^i) for i in
|
|
// 0..n-1 where n is the curve's bit size (256 in the case of secp256k1)
|
|
// the coordinates are recorded as Jacobian coordinates.
|
|
func (curve *KoblitzCurve) getDoublingPoints() [][3]fieldVal {
|
|
bitSize := curve.Params().BitSize
|
|
doublingPoints := make([][3]fieldVal, bitSize)
|
|
|
|
// initialize px, py, pz to the Jacobian coordinates for the base point
|
|
px, py := curve.bigAffineToField(curve.Gx, curve.Gy)
|
|
pz := new(fieldVal).SetInt(1)
|
|
for i := 0; i < bitSize; i++ {
|
|
doublingPoints[i] = [3]fieldVal{*px, *py, *pz}
|
|
// P = 2*P
|
|
curve.doubleJacobian(px, py, pz, px, py, pz)
|
|
}
|
|
return doublingPoints
|
|
}
|
|
|
|
// PrintBytePoints prints all the possible points per 8-bit window.
|
|
// normally, this is used to generate secp256k1.go
|
|
func (curve *KoblitzCurve) PrintBytePoints() {
|
|
bitSize := curve.Params().BitSize
|
|
byteSize := bitSize / 8
|
|
doublingPoints := curve.getDoublingPoints()
|
|
fmt.Println("// Copyright (c) 2014 Conformal Systems LLC.")
|
|
fmt.Println("// Use of this source code is governed by an ISC")
|
|
fmt.Println("// license that can be found in the LICENSE file.")
|
|
fmt.Println()
|
|
fmt.Println("package btcec")
|
|
fmt.Println()
|
|
fmt.Println("// Auto-generated file (see gensecp256k1.go)")
|
|
fmt.Printf("var secp256k1BytePoints = [%d][256][3]fieldVal{\n", byteSize)
|
|
// Segregate the bits into byte-sized windows
|
|
for byteNum := 0; byteNum < byteSize; byteNum++ {
|
|
fmt.Printf("\t{\n")
|
|
// grab the 8 bits that make up this byte from doublingPoints
|
|
startingBit := 8 * (byteSize - byteNum - 1)
|
|
computingPoints := doublingPoints[startingBit : startingBit+8]
|
|
// compute all points in this window
|
|
for i := 0; i < 256; i++ {
|
|
px, py, pz := new(fieldVal), new(fieldVal), new(fieldVal)
|
|
for j := 0; j < 8; j++ {
|
|
if i>>uint(j)&1 == 1 {
|
|
curve.addJacobian(px, py, pz, &computingPoints[j][0],
|
|
&computingPoints[j][1], &computingPoints[j][2], px, py, pz)
|
|
}
|
|
}
|
|
fmt.Printf("\t\t{\n\t\t\tfieldVal{[10]uint32{%d, %d, %d, %d, %d, %d, %d, %d, %d, %d}},\n", px.n[0], px.n[1], px.n[2], px.n[3], px.n[4], px.n[5], px.n[6], px.n[7], px.n[8], px.n[9])
|
|
fmt.Printf("\t\t\tfieldVal{[10]uint32{%d, %d, %d, %d, %d, %d, %d, %d, %d, %d}},\n", py.n[0], py.n[1], py.n[2], py.n[3], py.n[4], py.n[5], py.n[6], py.n[7], py.n[8], py.n[9])
|
|
fmt.Printf("\t\t\tfieldVal{[10]uint32{%d, %d, %d, %d, %d, %d, %d, %d, %d, %d}},\n\t\t},\n", pz.n[0], pz.n[1], pz.n[2], pz.n[3], pz.n[4], pz.n[5], pz.n[6], pz.n[7], pz.n[8], pz.n[9])
|
|
}
|
|
fmt.Printf("\t},\n")
|
|
}
|
|
fmt.Printf("}\n")
|
|
}
|