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  }