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 }