github.com/aigarnetwork/aigar@v0.0.0-20191115204914-d59a6eb70f8e/crypto/bn256/cloudflare/lattice.go (about)

     1  //  Copyright 2018 The go-ethereum Authors
     2  //  Copyright 2019 The go-aigar Authors
     3  //  This file is part of the go-aigar library.
     4  //
     5  //  The go-aigar library is free software: you can redistribute it and/or modify
     6  //  it under the terms of the GNU Lesser General Public License as published by
     7  //  the Free Software Foundation, either version 3 of the License, or
     8  //  (at your option) any later version.
     9  //
    10  //  The go-aigar library is distributed in the hope that it will be useful,
    11  //  but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    13  //  GNU Lesser General Public License for more details.
    14  //
    15  //  You should have received a copy of the GNU Lesser General Public License
    16  //  along with the go-aigar library. If not, see <http://www.gnu.org/licenses/>.
    17  
    18  package bn256
    19  
    20  import (
    21  	"math/big"
    22  )
    23  
    24  var half = new(big.Int).Rsh(Order, 1)
    25  
    26  var curveLattice = &lattice{
    27  	vectors: [][]*big.Int{
    28  		{bigFromBase10("147946756881789319000765030803803410728"), bigFromBase10("147946756881789319010696353538189108491")},
    29  		{bigFromBase10("147946756881789319020627676272574806254"), bigFromBase10("-147946756881789318990833708069417712965")},
    30  	},
    31  	inverse: []*big.Int{
    32  		bigFromBase10("147946756881789318990833708069417712965"),
    33  		bigFromBase10("147946756881789319010696353538189108491"),
    34  	},
    35  	det: bigFromBase10("43776485743678550444492811490514550177096728800832068687396408373151616991234"),
    36  }
    37  
    38  var targetLattice = &lattice{
    39  	vectors: [][]*big.Int{
    40  		{bigFromBase10("9931322734385697761"), bigFromBase10("9931322734385697761"), bigFromBase10("9931322734385697763"), bigFromBase10("9931322734385697764")},
    41  		{bigFromBase10("4965661367192848881"), bigFromBase10("4965661367192848881"), bigFromBase10("4965661367192848882"), bigFromBase10("-9931322734385697762")},
    42  		{bigFromBase10("-9931322734385697762"), bigFromBase10("-4965661367192848881"), bigFromBase10("4965661367192848881"), bigFromBase10("-4965661367192848882")},
    43  		{bigFromBase10("9931322734385697763"), bigFromBase10("-4965661367192848881"), bigFromBase10("-4965661367192848881"), bigFromBase10("-4965661367192848881")},
    44  	},
    45  	inverse: []*big.Int{
    46  		bigFromBase10("734653495049373973658254490726798021314063399421879442165"),
    47  		bigFromBase10("147946756881789319000765030803803410728"),
    48  		bigFromBase10("-147946756881789319005730692170996259609"),
    49  		bigFromBase10("1469306990098747947464455738335385361643788813749140841702"),
    50  	},
    51  	det: new(big.Int).Set(Order),
    52  }
    53  
    54  type lattice struct {
    55  	vectors [][]*big.Int
    56  	inverse []*big.Int
    57  	det     *big.Int
    58  }
    59  
    60  // decompose takes a scalar mod Order as input and finds a short, positive decomposition of it wrt to the lattice basis.
    61  func (l *lattice) decompose(k *big.Int) []*big.Int {
    62  	n := len(l.inverse)
    63  
    64  	// Calculate closest vector in lattice to <k,0,0,...> with Babai's rounding.
    65  	c := make([]*big.Int, n)
    66  	for i := 0; i < n; i++ {
    67  		c[i] = new(big.Int).Mul(k, l.inverse[i])
    68  		round(c[i], l.det)
    69  	}
    70  
    71  	// Transform vectors according to c and subtract <k,0,0,...>.
    72  	out := make([]*big.Int, n)
    73  	temp := new(big.Int)
    74  
    75  	for i := 0; i < n; i++ {
    76  		out[i] = new(big.Int)
    77  
    78  		for j := 0; j < n; j++ {
    79  			temp.Mul(c[j], l.vectors[j][i])
    80  			out[i].Add(out[i], temp)
    81  		}
    82  
    83  		out[i].Neg(out[i])
    84  		out[i].Add(out[i], l.vectors[0][i]).Add(out[i], l.vectors[0][i])
    85  	}
    86  	out[0].Add(out[0], k)
    87  
    88  	return out
    89  }
    90  
    91  func (l *lattice) Precompute(add func(i, j uint)) {
    92  	n := uint(len(l.vectors))
    93  	total := uint(1) << n
    94  
    95  	for i := uint(0); i < n; i++ {
    96  		for j := uint(0); j < total; j++ {
    97  			if (j>>i)&1 == 1 {
    98  				add(i, j)
    99  			}
   100  		}
   101  	}
   102  }
   103  
   104  func (l *lattice) Multi(scalar *big.Int) []uint8 {
   105  	decomp := l.decompose(scalar)
   106  
   107  	maxLen := 0
   108  	for _, x := range decomp {
   109  		if x.BitLen() > maxLen {
   110  			maxLen = x.BitLen()
   111  		}
   112  	}
   113  
   114  	out := make([]uint8, maxLen)
   115  	for j, x := range decomp {
   116  		for i := 0; i < maxLen; i++ {
   117  			out[i] += uint8(x.Bit(i)) << uint(j)
   118  		}
   119  	}
   120  
   121  	return out
   122  }
   123  
   124  // round sets num to num/denom rounded to the nearest integer.
   125  func round(num, denom *big.Int) {
   126  	r := new(big.Int)
   127  	num.DivMod(num, denom, r)
   128  
   129  	if r.Cmp(half) == 1 {
   130  		num.Add(num, big.NewInt(1))
   131  	}
   132  }