github.com/theQRL/go-zond@v0.1.1/crypto/bn256/cloudflare/gfp.go (about) 1 package bn256 2 3 import ( 4 "errors" 5 "fmt" 6 ) 7 8 type gfP [4]uint64 9 10 func newGFp(x int64) (out *gfP) { 11 if x >= 0 { 12 out = &gfP{uint64(x)} 13 } else { 14 out = &gfP{uint64(-x)} 15 gfpNeg(out, out) 16 } 17 18 montEncode(out, out) 19 return out 20 } 21 22 func (e *gfP) String() string { 23 return fmt.Sprintf("%16.16x%16.16x%16.16x%16.16x", e[3], e[2], e[1], e[0]) 24 } 25 26 func (e *gfP) Set(f *gfP) { 27 e[0] = f[0] 28 e[1] = f[1] 29 e[2] = f[2] 30 e[3] = f[3] 31 } 32 33 func (e *gfP) Invert(f *gfP) { 34 bits := [4]uint64{0x3c208c16d87cfd45, 0x97816a916871ca8d, 0xb85045b68181585d, 0x30644e72e131a029} 35 36 sum, power := &gfP{}, &gfP{} 37 sum.Set(rN1) 38 power.Set(f) 39 40 for word := 0; word < 4; word++ { 41 for bit := uint(0); bit < 64; bit++ { 42 if (bits[word]>>bit)&1 == 1 { 43 gfpMul(sum, sum, power) 44 } 45 gfpMul(power, power, power) 46 } 47 } 48 49 gfpMul(sum, sum, r3) 50 e.Set(sum) 51 } 52 53 func (e *gfP) Marshal(out []byte) { 54 for w := uint(0); w < 4; w++ { 55 for b := uint(0); b < 8; b++ { 56 out[8*w+b] = byte(e[3-w] >> (56 - 8*b)) 57 } 58 } 59 } 60 61 func (e *gfP) Unmarshal(in []byte) error { 62 // Unmarshal the bytes into little endian form 63 for w := uint(0); w < 4; w++ { 64 e[3-w] = 0 65 for b := uint(0); b < 8; b++ { 66 e[3-w] += uint64(in[8*w+b]) << (56 - 8*b) 67 } 68 } 69 // Ensure the point respects the curve modulus 70 for i := 3; i >= 0; i-- { 71 if e[i] < p2[i] { 72 return nil 73 } 74 if e[i] > p2[i] { 75 return errors.New("bn256: coordinate exceeds modulus") 76 } 77 } 78 return errors.New("bn256: coordinate equals modulus") 79 } 80 81 func montEncode(c, a *gfP) { gfpMul(c, a, r2) } 82 func montDecode(c, a *gfP) { gfpMul(c, a, &gfP{1}) }