github.com/piotrnar/gocoin@v0.0.0-20240512203912-faa0448c5e96/lib/secp256k1/xy.go (about) 1 package secp256k1 2 3 import ( 4 "fmt" 5 ) 6 7 type XY struct { 8 X, Y Field 9 Infinity bool 10 } 11 12 func (ge *XY) Print(lab string) { 13 if ge.Infinity { 14 fmt.Println(lab + " - Infinity") 15 return 16 } 17 fmt.Println(lab+".X:", ge.X.String()) 18 fmt.Println(lab+".Y:", ge.Y.String()) 19 } 20 21 func (elem *XY) ParsePubkey(pub []byte) bool { 22 if len(pub) == 33 && (pub[0] == 0x02 || pub[0] == 0x03) { 23 elem.X.SetB32(pub[1:33]) 24 elem.SetXO(&elem.X, pub[0] == 0x03) 25 } else if len(pub) == 65 && (pub[0] == 0x04 || pub[0] == 0x06 || pub[0] == 0x07) { 26 elem.X.SetB32(pub[1:33]) 27 elem.Y.SetB32(pub[33:65]) 28 if (pub[0] == 0x06 || pub[0] == 0x07) && elem.Y.IsOdd() != (pub[0] == 0x07) { 29 return false 30 } 31 } else { 32 return false 33 } 34 return true 35 } 36 37 func (elem *XY) ParseXOnlyPubkey(pub []byte) bool { 38 elem.X.SetB32(pub) 39 elem.SetXO(&elem.X, false) 40 return true 41 } 42 43 // Bytes returns the serialized key in uncompressed format "<04> <X> <Y>" 44 // or in compressed format: "<02> <X>", eventually "<03> <X>". 45 func (pub *XY) Bytes(compressed bool) (raw []byte) { 46 if compressed { 47 raw = make([]byte, 33) 48 if pub.Y.IsOdd() { 49 raw[0] = 0x03 50 } else { 51 raw[0] = 0x02 52 } 53 pub.X.GetB32(raw[1:]) 54 } else { 55 raw = make([]byte, 65) 56 raw[0] = 0x04 57 pub.X.GetB32(raw[1:33]) 58 pub.Y.GetB32(raw[33:65]) 59 } 60 return 61 } 62 63 func (r *XY) SetXY(X, Y *Field) { 64 r.Infinity = false 65 r.X = *X 66 r.Y = *Y 67 } 68 69 func (a *XY) IsValid() bool { 70 if a.Infinity { 71 return false 72 } 73 var y2, x3, c Field 74 a.Y.Sqr(&y2) 75 a.X.Sqr(&x3) 76 x3.Mul(&x3, &a.X) 77 c.SetInt(7) 78 x3.SetAdd(&c) 79 y2.Normalize() 80 x3.Normalize() 81 return y2.Equals(&x3) 82 } 83 84 func (r *XY) SetXYZ(a *XYZ) { 85 var z2, z3 Field 86 a.Z.InvVar(&a.Z) 87 a.Z.Sqr(&z2) 88 a.Z.Mul(&z3, &z2) 89 a.X.Mul(&a.X, &z2) 90 a.Y.Mul(&a.Y, &z3) 91 a.Z.SetInt(1) 92 r.Infinity = a.Infinity 93 r.X = a.X 94 r.Y = a.Y 95 } 96 97 func (a *XY) precomp(w int) (pre []XY) { 98 pre = make([]XY, (1 << (uint(w) - 2))) 99 pre[0] = *a 100 var X, d, tmp XYZ 101 X.SetXY(a) 102 X.Double(&d) 103 for i := 1; i < len(pre); i++ { 104 d.AddXY(&tmp, &pre[i-1]) 105 pre[i].SetXYZ(&tmp) 106 } 107 return 108 } 109 110 func (a *XY) Neg(r *XY) { 111 r.Infinity = a.Infinity 112 r.X = a.X 113 r.Y = a.Y 114 r.Y.Normalize() 115 r.Y.Negate(&r.Y, 1) 116 } 117 118 func (r *XY) SetXO(X *Field, odd bool) { 119 var c, x2, x3 Field 120 r.X = *X 121 X.Sqr(&x2) 122 X.Mul(&x3, &x2) 123 r.Infinity = false 124 c.SetInt(7) 125 c.SetAdd(&x3) 126 c.Sqrt(&r.Y) 127 r.Y.Normalize() 128 if r.Y.IsOdd() != odd { 129 r.Y.Negate(&r.Y, 1) 130 } 131 r.Y.Normalize() 132 } 133 134 func (pk *XY) AddXY(a *XY) { 135 var xyz XYZ 136 xyz.SetXY(pk) 137 xyz.AddXY(&xyz, a) 138 pk.SetXYZ(&xyz) 139 } 140 141 func (pk *XY) GetPublicKey(out []byte) { 142 pk.X.Normalize() // See GitHub issue #15 143 pk.X.GetB32(out[1:33]) 144 if len(out) == 65 { 145 out[0] = 0x04 146 pk.Y.Normalize() 147 pk.Y.GetB32(out[33:65]) 148 } else { 149 if pk.Y.IsOdd() { 150 out[0] = 0x03 151 } else { 152 out[0] = 0x02 153 } 154 } 155 }