github.com/jiajun1992/watercarver@v0.0.0-20191031150618-dfc2b17c0c4a/go-ethereum/ctcrypto/crypto/multiexp.go (about) 1 package crypto 2 3 import ( 4 "fmt" 5 ) 6 7 var Identity_p3 ExtendedGroupElement 8 9 type MultiexpData struct { 10 Scalar Key 11 Point ExtendedGroupElement 12 } 13 14 func AppendMultiexpData(data *[]MultiexpData, point *Key, scalar *Key) { 15 var _point ExtendedGroupElement 16 _point.FromBytes(point) 17 *data = append(*data, MultiexpData{Point:_point, Scalar:*scalar}) 18 } 19 20 type Straus_cached_data struct { 21 Multiples [][]CachedGroupElement 22 } 23 24 const STRAUS_C = 4 25 26 func lessThan(k0 *Key, k1 *Key) bool { 27 for n := 31; n >= 0; n-- { 28 if k0[n] < k1[n] { 29 return true 30 } 31 if k0[n] > k1[n] { 32 return false 33 } 34 } 35 return false 36 } 37 38 func pow2(n int) (res *Key) { 39 res = new(Key) 40 *res = Zero 41 res[n >> 3] |= 1 << uint(n & 7) 42 return 43 } 44 45 func test(k Key, n int) int { 46 if n >= 256 { 47 return 0 48 } 49 return int(k[n >> 3] & (1 << uint(n & 7))) 50 } 51 52 func add(p3 *ExtendedGroupElement, other *CachedGroupElement) { 53 var p1 CompletedGroupElement 54 geAdd(&p1, p3, other) 55 p1.ToExtended(p3) 56 } 57 58 func add3_3(p3 *ExtendedGroupElement, other *ExtendedGroupElement) { 59 var cached CachedGroupElement 60 other.ToCached(&cached) 61 add(p3, &cached) 62 } 63 64 func straus(data *[]MultiexpData, cache *Straus_cached_data, STEP int) (result Key, err error) { 65 if cache != nil && (len(cache.Multiples) < 1 || len(cache.Multiples[1]) < len(*data)) { 66 err = fmt.Errorf("Cache is too small ") 67 return 68 } 69 if STEP <= 0 { 70 STEP = 192 71 } 72 local_cache := cache 73 if local_cache == nil { 74 local_cache, err = straus_init_cache(data, 0) 75 if err != nil { 76 return 77 } 78 } 79 80 var cached CachedGroupElement 81 var p1 CompletedGroupElement 82 83 digits := make([]uint8, 64 * len(*data)) 84 for j := 0; j < len(*data); j++ { 85 bytes := (*data)[j].Scalar[:] 86 for i := 0; i < 64; i += 2 { 87 digits[j * 64 + i] = bytes[0] & 0xf 88 digits[j * 64 + i + 1] = bytes[0] >> 4 89 bytes = bytes[1:] 90 } 91 } 92 maxscalar := Zero 93 for i := 0; i < len(*data); i++ { 94 if lessThan(&maxscalar, &(*data)[i].Scalar) { 95 maxscalar = (*data)[i].Scalar 96 } 97 } 98 start_i := 0 99 for start_i < 256 && !(lessThan(&maxscalar, pow2(start_i))) { 100 start_i += STRAUS_C 101 } 102 103 res_p3 := Identity_p3 104 105 for start_offset := 0; start_offset < len(*data); start_offset += STEP { 106 num_points := len(*data) - start_offset 107 if num_points > STEP { 108 num_points = STEP 109 } 110 111 band_p3 := Identity_p3 112 i := start_i 113 skip := false 114 if !(i < STRAUS_C) { 115 skip = true 116 } 117 for !(i < STRAUS_C) { 118 if !skip { 119 var p2 ProjectiveGroupElement 120 band_p3.ToProjective(&p2) 121 for j:= 0; j < STRAUS_C; j++ { 122 p2.Double(&p1) 123 if j == STRAUS_C - 1 { 124 p1.ToExtended(&band_p3) 125 } else { 126 p1.ToProjective(&p2) 127 } 128 } 129 } 130 i -= STRAUS_C 131 for j := start_offset; j < start_offset + num_points; j++ { 132 digit := digits[j * 64 + i / 4] 133 134 if digit != 0 { 135 geAdd(&p1, &band_p3, &local_cache.Multiples[digit][j]) 136 p1.ToExtended(&band_p3) 137 } 138 } 139 skip = false 140 } 141 142 band_p3.ToCached(&cached) 143 geAdd(&p1, &res_p3, &cached) 144 p1.ToExtended(&res_p3) 145 } 146 147 res_p3.ToBytes(&result) 148 return 149 } 150 151 func straus_init_cache(data *[]MultiexpData, N int) (cache *Straus_cached_data, err error) { 152 if N == 0 { 153 N = len(*data) 154 } 155 if N > len(*data) { 156 err = fmt.Errorf("Bad cache base data ") 157 return 158 } 159 var p1 CompletedGroupElement 160 var p3 ExtendedGroupElement 161 cache = new(Straus_cached_data) 162 cache.Multiples = make([][]CachedGroupElement, 1 << STRAUS_C) 163 offset := 0 164 cache.Multiples[1] = make([]CachedGroupElement, N) 165 for i := offset; i < N; i++{ 166 (*data)[i].Point.ToCached(&cache.Multiples[1][i]) 167 } 168 for i := 2; i < (1 << STRAUS_C); i++ { 169 cache.Multiples[i] = make([]CachedGroupElement, N) 170 } 171 for j := offset; j < N; j++ { 172 for i := 2; i < (1 << STRAUS_C); i++ { 173 geAdd(&p1, &(*data)[j].Point, &cache.Multiples[i-1][j]) 174 p1.ToExtended(&p3) 175 p3.ToCached(&cache.Multiples[i][j]) 176 } 177 } 178 return 179 } 180 181 func pippenger(data *[]MultiexpData, cache *Pippenger_cached_data, cache_size int, c int) (_result Key, err error) { 182 if cache != nil && cache_size == 0 { 183 cache_size = len(cache.cached) 184 } 185 if cache != nil && cache_size > len(cache.cached) { 186 err = fmt.Errorf("Cache is too small ") 187 return 188 } 189 if c == 0 { 190 c = get_pippenger_c(len(*data)) 191 } 192 if c > 9 { 193 err = fmt.Errorf("c is too large ") 194 return 195 } 196 197 result := Identity_p3 198 result_init := false 199 buckets := make([]ExtendedGroupElement, 1 << uint(c)) 200 var buckets_init []bool 201 local_cache := cache 202 if local_cache == nil { 203 local_cache, err = pippenger_init_cache(data, 0, 0) 204 if err != nil { 205 return 206 } 207 //cache_size = len(*data) 208 } 209 var local_cache2 *Pippenger_cached_data 210 if len(*data) > cache_size { 211 local_cache2, err = pippenger_init_cache(data, cache_size, 0) 212 if err != nil { 213 return 214 } 215 } 216 217 maxscalar := Zero 218 for i := 0; i < len(*data); i++ { 219 if lessThan(&maxscalar, &(*data)[i].Scalar) { 220 maxscalar = (*data)[i].Scalar 221 } 222 } 223 groups := 0 224 for groups < 256 && !(lessThan(&maxscalar, pow2(groups))) { 225 groups++ 226 } 227 groups = (groups + c - 1) / c 228 229 for k := groups - 1; k >= 0; k-- { 230 if result_init { 231 var p2 ProjectiveGroupElement 232 result.ToProjective(&p2) 233 for i := 0; i < c; i++ { 234 var p1 CompletedGroupElement 235 p2.Double(&p1) 236 if i == c - 1 { 237 p1.ToExtended(&result) 238 } else { 239 p1.ToProjective(&p2) 240 } 241 } 242 } 243 buckets_init = make([]bool, 1 << uint(c)) 244 245 for i := 0; i < len(*data); i++ { 246 bucket := 0 247 for j := 0; j < c; j++ { 248 if test((*data)[i].Scalar, k * c + j) != 0 { 249 bucket |= 1 << uint(j) 250 } 251 } 252 if bucket == 0 { 253 continue 254 } 255 if bucket >= (1 << uint(c)) { 256 err = fmt.Errorf("bucket overflow") 257 return 258 } 259 if buckets_init[bucket] { 260 if i < cache_size { 261 add(&buckets[bucket], &local_cache.cached[i]) 262 } else { 263 add(&buckets[bucket], &local_cache2.cached[i - cache_size]) 264 } 265 } else { 266 buckets[bucket] = (*data)[i].Point 267 buckets_init[bucket] = true 268 } 269 } 270 271 var pail ExtendedGroupElement 272 pail_init := false 273 for i := (1 << uint(c)) - 1; i > 0; i-- { 274 if buckets_init[i] { 275 if pail_init { 276 add3_3(&pail, &buckets[i]) 277 } else { 278 pail = buckets[i] 279 pail_init = true 280 } 281 } 282 if pail_init { 283 if result_init { 284 add3_3(&result, &pail) 285 } else { 286 result = pail 287 result_init = true 288 } 289 } 290 /* 291 var tmp Key 292 pail.ToBytes(&tmp) 293 fmt.Printf("k: %d i:%d pail:%s ", k, i, tmp) 294 result.ToBytes(&tmp) 295 fmt.Printf("result:%s\n", tmp) 296 */ 297 } 298 } 299 300 result.ToBytes(&_result) 301 return 302 } 303 304 func get_pippenger_c(N int) int { 305 if N <= 13 { 306 return 2 307 } 308 if N <= 29 { 309 return 3 310 } 311 if N <= 83 { 312 return 4 313 } 314 if N <= 185 { 315 return 5 316 } 317 if N <= 465 { 318 return 6 319 } 320 if N <= 1180 { 321 return 7 322 } 323 if N <= 2295 { 324 return 8 325 } 326 return 9 327 } 328 329 type Pippenger_cached_data struct { 330 cached []CachedGroupElement 331 } 332 333 func pippenger_init_cache(data *[]MultiexpData, start_offset int, N int) (cache *Pippenger_cached_data, err error) { 334 if start_offset > len(*data) { 335 err = fmt.Errorf("Bad cache base data ") 336 return 337 } 338 if N == 0 { 339 N = len(*data) - start_offset 340 } 341 if N > len(*data) - start_offset { 342 err = fmt.Errorf("Bad cache base data ") 343 return 344 } 345 346 cache = new(Pippenger_cached_data) 347 348 cache.cached = make([]CachedGroupElement, N) 349 for i := 0; i < N; i++ { 350 (*data)[i + start_offset].Point.ToCached(&cache.cached[i]) 351 } 352 return 353 } 354 355 func Multiexp(data *[]MultiexpData, HiGi_size int) (Key, error) { 356 if HiGi_size > 0 { 357 if HiGi_size <= 232 && len(*data) == HiGi_size { 358 return straus(data, straus_HiGi_cache, 0) 359 } else { 360 return pippenger(data, pippenger_HiGi_cache, HiGi_size, get_pippenger_c(len(*data))) 361 } 362 } else { 363 if len(*data) <= 95 { 364 return straus(data, nil, 0) 365 } else { 366 return pippenger(data, nil, 0, get_pippenger_c(len(*data))) 367 } 368 } 369 } 370 371 const STRAUS_SIZE_LIMIT = 232 372 const PIPPENGER_SIZE_LIMIT = 0 373 var straus_HiGi_cache *Straus_cached_data 374 var pippenger_HiGi_cache *Pippenger_cached_data 375 376 func InitCache(data []MultiexpData) { 377 Identity_p3.FromBytes(&Identity) 378 pstraus_HiGi_cache, err := straus_init_cache(&data, STRAUS_SIZE_LIMIT) 379 if err != nil { 380 panic("fail to init cache for multiexp ") 381 } 382 ppippenger_HiGi_cache, err := pippenger_init_cache(&data, 0, PIPPENGER_SIZE_LIMIT) 383 if err != nil { 384 panic("fail to init cache for multiexp ") 385 } 386 straus_HiGi_cache = pstraus_HiGi_cache 387 pippenger_HiGi_cache = ppippenger_HiGi_cache 388 }