precompute.go raw

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