github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/crypto/bn256/google/curve.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 12:09:36</date>
    10  //</624342625985499136>
    11  
    12  //版权所有2012 Go作者。版权所有。
    13  //此源代码的使用受BSD样式的控制
    14  //可以在许可文件中找到的许可证。
    15  
    16  package bn256
    17  
    18  import (
    19  	"math/big"
    20  )
    21  
    22  //curvePoint实现椭圆曲线y?=x?+3。积分保留在
    23  //雅可比形式,有效时t=z²。G_是曲线上的一组点
    24  //GF(P)。
    25  type curvePoint struct {
    26  	x, y, z, t *big.Int
    27  }
    28  
    29  var curveB = new(big.Int).SetInt64(3)
    30  
    31  //曲线发电机是G_的发电机。
    32  var curveGen = &curvePoint{
    33  	new(big.Int).SetInt64(1),
    34  	new(big.Int).SetInt64(2),
    35  	new(big.Int).SetInt64(1),
    36  	new(big.Int).SetInt64(1),
    37  }
    38  
    39  func newCurvePoint(pool *bnPool) *curvePoint {
    40  	return &curvePoint{
    41  		pool.Get(),
    42  		pool.Get(),
    43  		pool.Get(),
    44  		pool.Get(),
    45  	}
    46  }
    47  
    48  func (c *curvePoint) String() string {
    49  	c.MakeAffine(new(bnPool))
    50  	return "(" + c.x.String() + ", " + c.y.String() + ")"
    51  }
    52  
    53  func (c *curvePoint) Put(pool *bnPool) {
    54  	pool.Put(c.x)
    55  	pool.Put(c.y)
    56  	pool.Put(c.z)
    57  	pool.Put(c.t)
    58  }
    59  
    60  func (c *curvePoint) Set(a *curvePoint) {
    61  	c.x.Set(a.x)
    62  	c.y.Set(a.y)
    63  	c.z.Set(a.z)
    64  	c.t.Set(a.t)
    65  }
    66  
    67  //is on curve返回真正的iff c在曲线上,其中c必须是仿射形式。
    68  func (c *curvePoint) IsOnCurve() bool {
    69  	yy := new(big.Int).Mul(c.y, c.y)
    70  	xxx := new(big.Int).Mul(c.x, c.x)
    71  	xxx.Mul(xxx, c.x)
    72  	yy.Sub(yy, xxx)
    73  	yy.Sub(yy, curveB)
    74  	if yy.Sign() < 0 || yy.Cmp(P) >= 0 {
    75  		yy.Mod(yy, P)
    76  	}
    77  	return yy.Sign() == 0
    78  }
    79  
    80  func (c *curvePoint) SetInfinity() {
    81  	c.z.SetInt64(0)
    82  }
    83  
    84  func (c *curvePoint) IsInfinity() bool {
    85  	return c.z.Sign() == 0
    86  }
    87  
    88  func (c *curvePoint) Add(a, b *curvePoint, pool *bnPool) {
    89  	if a.IsInfinity() {
    90  		c.Set(b)
    91  		return
    92  	}
    93  	if b.IsInfinity() {
    94  		c.Set(a)
    95  		return
    96  	}
    97  
    98  //见http://hyper椭圆形.org/efd/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3
    99  
   100  //通过替换a=[x1:y1:z1]和b=[x2:y2:z2]来规范化点。
   101  //通过[U1:S1:Z1·Z2]和[U2:S2:Z1·Z2]
   102  //式中:U1=x1·z2?、S1=y1·z2?、U1=x2·z1?、S2=y2·z1??
   103  	z1z1 := pool.Get().Mul(a.z, a.z)
   104  	z1z1.Mod(z1z1, P)
   105  	z2z2 := pool.Get().Mul(b.z, b.z)
   106  	z2z2.Mod(z2z2, P)
   107  	u1 := pool.Get().Mul(a.x, z2z2)
   108  	u1.Mod(u1, P)
   109  	u2 := pool.Get().Mul(b.x, z1z1)
   110  	u2.Mod(u2, P)
   111  
   112  	t := pool.Get().Mul(b.z, z2z2)
   113  	t.Mod(t, P)
   114  	s1 := pool.Get().Mul(a.y, t)
   115  	s1.Mod(s1, P)
   116  
   117  	t.Mul(a.z, z1z1)
   118  	t.Mod(t, P)
   119  	s2 := pool.Get().Mul(b.y, t)
   120  	s2.Mod(s2, P)
   121  
   122  //计算x=(2h)2(s²-u1-u2)
   123  //其中s=(s2-s1)/(u2-u1)是线路通过的坡度
   124  //(U1、S1)和(U2、S2)。额外因子2h=2(u2-u1)来自下面的z值。
   125  //这也是:
   126  //4(s2-s1)2-4h 2(u1+u2)=4(s2-s1)2-4h 3-4h 2(2u1)
   127  //R=J-2V
   128  //以及下面的注释。
   129  	h := pool.Get().Sub(u2, u1)
   130  	xEqual := h.Sign() == 0
   131  
   132  	t.Add(h, h)
   133  //I= 4H
   134  	i := pool.Get().Mul(t, t)
   135  	i.Mod(i, P)
   136  //J= 4H
   137  	j := pool.Get().Mul(h, i)
   138  	j.Mod(j, P)
   139  
   140  	t.Sub(s2, s1)
   141  	yEqual := t.Sign() == 0
   142  	if xEqual && yEqual {
   143  		c.Double(a, pool)
   144  		return
   145  	}
   146  	r := pool.Get().Add(t, t)
   147  
   148  	v := pool.Get().Mul(u1, i)
   149  	v.Mod(v, P)
   150  
   151  //T4=4(S2-S1)
   152  	t4 := pool.Get().Mul(r, r)
   153  	t4.Mod(t4, P)
   154  	t.Add(v, v)
   155  	t6 := pool.Get().Sub(t4, j)
   156  	c.x.Sub(t6, t)
   157  
   158  //设置y=—(2h)³(s1+s*(x/4h²-u1))
   159  //这也是
   160  //y=-2·s1·j-(s2-s1)(2x-2i·u1)=r(v-x)-2·s1·j
   161  t.Sub(v, c.x) //T7
   162  t4.Mul(s1, j) //T8
   163  	t4.Mod(t4, P)
   164  t6.Add(t4, t4) //T9
   165  t4.Mul(r, t)   //T10
   166  	t4.Mod(t4, P)
   167  	c.y.Sub(t4, t6)
   168  
   169  //设置z=2(u2-u1)·z1·z2=2h·z1·z2
   170  t.Add(a.z, b.z) //T11
   171  t4.Mul(t, t)    //T12
   172  	t4.Mod(t4, P)
   173  t.Sub(t4, z1z1) //T13
   174  t4.Sub(t, z2z2) //T14
   175  	c.z.Mul(t4, h)
   176  	c.z.Mod(c.z, P)
   177  
   178  	pool.Put(z1z1)
   179  	pool.Put(z2z2)
   180  	pool.Put(u1)
   181  	pool.Put(u2)
   182  	pool.Put(t)
   183  	pool.Put(s1)
   184  	pool.Put(s2)
   185  	pool.Put(h)
   186  	pool.Put(i)
   187  	pool.Put(j)
   188  	pool.Put(r)
   189  	pool.Put(v)
   190  	pool.Put(t4)
   191  	pool.Put(t6)
   192  }
   193  
   194  func (c *curvePoint) Double(a *curvePoint, pool *bnPool) {
   195  //请参阅http://hyper椭圆形.org/efd/g1p/auto-code/shortw/jacobian-0/double/dbl-2009-l.op3
   196  	A := pool.Get().Mul(a.x, a.x)
   197  	A.Mod(A, P)
   198  	B := pool.Get().Mul(a.y, a.y)
   199  	B.Mod(B, P)
   200  	C_ := pool.Get().Mul(B, B)
   201  	C_.Mod(C_, P)
   202  
   203  	t := pool.Get().Add(a.x, B)
   204  	t2 := pool.Get().Mul(t, t)
   205  	t2.Mod(t2, P)
   206  	t.Sub(t2, A)
   207  	t2.Sub(t, C_)
   208  	d := pool.Get().Add(t2, t2)
   209  	t.Add(A, A)
   210  	e := pool.Get().Add(t, A)
   211  	f := pool.Get().Mul(e, e)
   212  	f.Mod(f, P)
   213  
   214  	t.Add(d, d)
   215  	c.x.Sub(f, t)
   216  
   217  	t.Add(C_, C_)
   218  	t2.Add(t, t)
   219  	t.Add(t2, t2)
   220  	c.y.Sub(d, c.x)
   221  	t2.Mul(e, c.y)
   222  	t2.Mod(t2, P)
   223  	c.y.Sub(t2, t)
   224  
   225  	t.Mul(a.y, a.z)
   226  	t.Mod(t, P)
   227  	c.z.Add(t, t)
   228  
   229  	pool.Put(A)
   230  	pool.Put(B)
   231  	pool.Put(C_)
   232  	pool.Put(t)
   233  	pool.Put(t2)
   234  	pool.Put(d)
   235  	pool.Put(e)
   236  	pool.Put(f)
   237  }
   238  
   239  func (c *curvePoint) Mul(a *curvePoint, scalar *big.Int, pool *bnPool) *curvePoint {
   240  	sum := newCurvePoint(pool)
   241  	sum.SetInfinity()
   242  	t := newCurvePoint(pool)
   243  
   244  	for i := scalar.BitLen(); i >= 0; i-- {
   245  		t.Double(sum, pool)
   246  		if scalar.Bit(i) != 0 {
   247  			sum.Add(t, a, pool)
   248  		} else {
   249  			sum.Set(t)
   250  		}
   251  	}
   252  
   253  	c.Set(sum)
   254  	sum.Put(pool)
   255  	t.Put(pool)
   256  	return c
   257  }
   258  
   259  //makeaffine将c转换为affine形式并返回c。如果c是∞,则它设置
   260  //C到0:1:0。
   261  func (c *curvePoint) MakeAffine(pool *bnPool) *curvePoint {
   262  	if words := c.z.Bits(); len(words) == 1 && words[0] == 1 {
   263  		return c
   264  	}
   265  	if c.IsInfinity() {
   266  		c.x.SetInt64(0)
   267  		c.y.SetInt64(1)
   268  		c.z.SetInt64(0)
   269  		c.t.SetInt64(0)
   270  		return c
   271  	}
   272  	zInv := pool.Get().ModInverse(c.z, P)
   273  	t := pool.Get().Mul(c.y, zInv)
   274  	t.Mod(t, P)
   275  	zInv2 := pool.Get().Mul(zInv, zInv)
   276  	zInv2.Mod(zInv2, P)
   277  	c.y.Mul(t, zInv2)
   278  	c.y.Mod(c.y, P)
   279  	t.Mul(c.x, zInv2)
   280  	t.Mod(t, P)
   281  	c.x.Set(t)
   282  	c.z.SetInt64(1)
   283  	c.t.SetInt64(1)
   284  
   285  	pool.Put(zInv)
   286  	pool.Put(t)
   287  	pool.Put(zInv2)
   288  
   289  	return c
   290  }
   291  
   292  func (c *curvePoint) Negative(a *curvePoint) {
   293  	c.x.Set(a.x)
   294  	c.y.Neg(a.y)
   295  	c.z.Set(a.z)
   296  	c.t.SetInt64(0)
   297  }
   298