github.com/chain5j/chain5j-pkg@v1.0.7/crypto/signature/secp256k1/btcecv1/precompute.go (about)

     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  
     5  package btcecv1
     6  
     7  import (
     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.
    23  func 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  }