mirror of
https://github.com/Instadapp/Swap-Aggregator-Subgraph.git
synced 2024-07-29 21:57:12 +00:00
183 lines
4.2 KiB
JavaScript
183 lines
4.2 KiB
JavaScript
'use strict'
|
|
var Buffer = require('safe-buffer').Buffer
|
|
var BN = require('./bn')
|
|
var ECJPoint = require('./ecjpoint')
|
|
|
|
function ECPoint (x, y) {
|
|
if (x === null && y === null) {
|
|
this.x = this.y = null
|
|
this.inf = true
|
|
} else {
|
|
this.x = x
|
|
this.y = y
|
|
this.inf = false
|
|
}
|
|
}
|
|
|
|
ECPoint.fromPublicKey = function (publicKey) {
|
|
var first = publicKey[0]
|
|
var x
|
|
var y
|
|
|
|
if (publicKey.length === 33 && (first === 0x02 || first === 0x03)) {
|
|
x = BN.fromBuffer(publicKey.slice(1, 33))
|
|
|
|
// overflow
|
|
if (x.ucmp(BN.p) >= 0) return null
|
|
|
|
// create from X
|
|
y = x.redSqr().redMul(x).redIAdd7().redSqrt()
|
|
if (y === null) return null
|
|
if ((first === 0x03) !== y.isOdd()) y = y.redNeg()
|
|
|
|
return new ECPoint(x, y)
|
|
}
|
|
|
|
if (publicKey.length === 65 && (first === 0x04 || first === 0x06 || first === 0x07)) {
|
|
x = BN.fromBuffer(publicKey.slice(1, 33))
|
|
y = BN.fromBuffer(publicKey.slice(33, 65))
|
|
|
|
// overflow
|
|
if (x.ucmp(BN.p) >= 0 || y.ucmp(BN.p) >= 0) return null
|
|
|
|
// is odd flag
|
|
if ((first === 0x06 || first === 0x07) && y.isOdd() !== (first === 0x07)) return null
|
|
|
|
// x*x*x + 7 = y*y
|
|
if (x.redSqr().redMul(x).redIAdd7().ucmp(y.redSqr()) !== 0) return null
|
|
|
|
return new ECPoint(x, y)
|
|
}
|
|
|
|
return null
|
|
}
|
|
|
|
ECPoint.prototype.toPublicKey = function (compressed) {
|
|
var x = this.x
|
|
var y = this.y
|
|
var publicKey
|
|
|
|
if (compressed) {
|
|
publicKey = Buffer.alloc(33)
|
|
publicKey[0] = y.isOdd() ? 0x03 : 0x02
|
|
x.toBuffer().copy(publicKey, 1)
|
|
} else {
|
|
publicKey = Buffer.alloc(65)
|
|
publicKey[0] = 0x04
|
|
x.toBuffer().copy(publicKey, 1)
|
|
y.toBuffer().copy(publicKey, 33)
|
|
}
|
|
|
|
return publicKey
|
|
}
|
|
|
|
ECPoint.fromECJPoint = function (p) {
|
|
if (p.inf) return new ECPoint(null, null)
|
|
|
|
var zinv = p.z.redInvm()
|
|
var zinv2 = zinv.redSqr()
|
|
var ax = p.x.redMul(zinv2)
|
|
var ay = p.y.redMul(zinv2).redMul(zinv)
|
|
|
|
return new ECPoint(ax, ay)
|
|
}
|
|
|
|
ECPoint.prototype.toECJPoint = function () {
|
|
if (this.inf) return new ECJPoint(null, null, null)
|
|
|
|
return new ECJPoint(this.x, this.y, ECJPoint.one)
|
|
}
|
|
|
|
ECPoint.prototype.neg = function () {
|
|
if (this.inf) return this
|
|
|
|
return new ECPoint(this.x, this.y.redNeg())
|
|
}
|
|
|
|
ECPoint.prototype.add = function (p) {
|
|
// O + P = P
|
|
if (this.inf) return p
|
|
|
|
// P + O = P
|
|
if (p.inf) return this
|
|
|
|
if (this.x.ucmp(p.x) === 0) {
|
|
// P + P = 2P
|
|
if (this.y.ucmp(p.y) === 0) return this.dbl()
|
|
// P + (-P) = O
|
|
return new ECPoint(null, null)
|
|
}
|
|
|
|
// s = (y - yp) / (x - xp)
|
|
// nx = s^2 - x - xp
|
|
// ny = s * (x - nx) - y
|
|
var s = this.y.redSub(p.y)
|
|
if (!s.isZero()) s = s.redMul(this.x.redSub(p.x).redInvm())
|
|
|
|
var nx = s.redSqr().redISub(this.x).redISub(p.x)
|
|
var ny = s.redMul(this.x.redSub(nx)).redISub(this.y)
|
|
return new ECPoint(nx, ny)
|
|
}
|
|
|
|
ECPoint.prototype.dbl = function () {
|
|
if (this.inf) return this
|
|
|
|
// 2P = O
|
|
var yy = this.y.redAdd(this.y)
|
|
if (yy.isZero()) return new ECPoint(null, null)
|
|
|
|
// s = (3 * x^2) / (2 * y)
|
|
// nx = s^2 - 2*x
|
|
// ny = s * (x - nx) - y
|
|
var x2 = this.x.redSqr()
|
|
var s = x2.redAdd(x2).redIAdd(x2).redMul(yy.redInvm())
|
|
|
|
var nx = s.redSqr().redISub(this.x.redAdd(this.x))
|
|
var ny = s.redMul(this.x.redSub(nx)).redISub(this.y)
|
|
return new ECPoint(nx, ny)
|
|
}
|
|
|
|
ECPoint.prototype.mul = function (num) {
|
|
// Algorithm 3.36 Window NAF method for point multiplication
|
|
var nafPoints = this._getNAFPoints(4)
|
|
var points = nafPoints.points
|
|
|
|
// Get NAF form
|
|
var naf = num.getNAF(nafPoints.wnd)
|
|
|
|
// Add `this`*(N+1) for every w-NAF index
|
|
var acc = new ECJPoint(null, null, null)
|
|
for (var i = naf.length - 1; i >= 0; i--) {
|
|
// Count zeroes
|
|
for (var k = 0; i >= 0 && naf[i] === 0; i--, ++k);
|
|
if (i >= 0) k += 1
|
|
acc = acc.dblp(k)
|
|
|
|
if (i < 0) break
|
|
|
|
// J +- P
|
|
var z = naf[i]
|
|
if (z > 0) {
|
|
acc = acc.mixedAdd(points[(z - 1) >> 1])
|
|
} else {
|
|
acc = acc.mixedAdd(points[(-z - 1) >> 1].neg())
|
|
}
|
|
}
|
|
|
|
return ECPoint.fromECJPoint(acc)
|
|
}
|
|
|
|
ECPoint.prototype._getNAFPoints1 = function () {
|
|
return { wnd: 1, points: [this] }
|
|
}
|
|
|
|
ECPoint.prototype._getNAFPoints = function (wnd) {
|
|
var points = new Array((1 << wnd) - 1)
|
|
points[0] = this
|
|
var dbl = this.dbl()
|
|
for (var i = 1; i < points.length; ++i) points[i] = points[i - 1].add(dbl)
|
|
return { wnd: wnd, points: points }
|
|
}
|
|
|
|
module.exports = ECPoint
|