1// Copyright 2015 The btcsuite developers
2// Use of this source code is governed by an ISC
3// license that can be found in the LICENSE file.
4
5package btcec
6
7import (
8	"compress/zlib"
9	"encoding/base64"
10	"encoding/binary"
11	"io/ioutil"
12	"strings"
13)
14
15//go:generate go run -tags gensecp256k1 genprecomps.go
16
17// loadS256BytePoints decompresses and deserializes the pre-computed byte points
18// used to accelerate scalar base multiplication for the secp256k1 curve.  This
19// approach is used since it allows the compile to use significantly less ram
20// and be performed much faster than it is with hard-coding the final in-memory
21// data structure.  At the same time, it is quite fast to generate the in-memory
22// data structure at init time with this approach versus computing the table.
23func loadS256BytePoints() error {
24	// There will be no byte points to load when generating them.
25	bp := secp256k1BytePoints
26	if len(bp) == 0 {
27		return nil
28	}
29
30	// Decompress the pre-computed table used to accelerate scalar base
31	// multiplication.
32	decoder := base64.NewDecoder(base64.StdEncoding, strings.NewReader(bp))
33	r, err := zlib.NewReader(decoder)
34	if err != nil {
35		return err
36	}
37	serialized, err := ioutil.ReadAll(r)
38	if err != nil {
39		return err
40	}
41
42	// Deserialize the precomputed byte points and set the curve to them.
43	offset := 0
44	var bytePoints [32][256][3]fieldVal
45	for byteNum := 0; byteNum < 32; byteNum++ {
46		// All points in this window.
47		for i := 0; i < 256; i++ {
48			px := &bytePoints[byteNum][i][0]
49			py := &bytePoints[byteNum][i][1]
50			pz := &bytePoints[byteNum][i][2]
51			for i := 0; i < 10; i++ {
52				px.n[i] = binary.LittleEndian.Uint32(serialized[offset:])
53				offset += 4
54			}
55			for i := 0; i < 10; i++ {
56				py.n[i] = binary.LittleEndian.Uint32(serialized[offset:])
57				offset += 4
58			}
59			for i := 0; i < 10; i++ {
60				pz.n[i] = binary.LittleEndian.Uint32(serialized[offset:])
61				offset += 4
62			}
63		}
64	}
65	secp256k1.bytePoints = &bytePoints
66	return nil
67}
68