mirror of
https://github.com/discountry/ritmex-bot.git
synced 2026-09-11 09:18:08 +00:00
feat: 添加 Lighter 适配器及相关功能,支持 trailing stops 和新的交易逻辑
This commit is contained in:
@@ -0,0 +1,441 @@
|
||||
package ecgfp5
|
||||
|
||||
import (
|
||||
g "github.com/elliottech/poseidon_crypto/field/goldilocks"
|
||||
gFp5 "github.com/elliottech/poseidon_crypto/field/goldilocks_quintic_extension"
|
||||
)
|
||||
|
||||
// A curve point.
|
||||
type ECgFp5Point struct {
|
||||
// Internally, we use the (x,u) fractional coordinates: for curve
|
||||
// point (x,y), we have (x,u) = (x,x/y) = (X/Z,U/T) (for the neutral
|
||||
// N, the u coordinate is 0).
|
||||
x, z, u, t gFp5.Element
|
||||
}
|
||||
|
||||
// Constants for ECgFp5Point
|
||||
var (
|
||||
A_ECgFp5Point = gFp5.FromUint64Array([5]uint64{2, 0, 0, 0, 0})
|
||||
|
||||
B1 = uint64(263)
|
||||
B_ECgFp5Point = gFp5.FromUint64Array([5]uint64{0, B1, 0, 0, 0})
|
||||
B_MUL2_ECgFp5Point = gFp5.FromUint64Array([5]uint64{0, 2 * B1, 0, 0, 0})
|
||||
B_MUL4_ECgFp5Point = gFp5.FromUint64Array([5]uint64{0, 4 * B1, 0, 0, 0})
|
||||
B_MUL16_ECgFp5Point = gFp5.FromUint64Array([5]uint64{0, 16 * B1, 0, 0, 0})
|
||||
|
||||
NEUTRAL_ECgFp5Point = ECgFp5Point{
|
||||
x: gFp5.FP5_ZERO,
|
||||
z: gFp5.FP5_ONE,
|
||||
u: gFp5.FP5_ZERO,
|
||||
t: gFp5.FP5_ONE,
|
||||
}
|
||||
|
||||
GENERATOR_ECgFp5Point = ECgFp5Point{
|
||||
x: gFp5.FromUint64Array([5]uint64{
|
||||
12883135586176881569,
|
||||
4356519642755055268,
|
||||
5248930565894896907,
|
||||
2165973894480315022,
|
||||
2448410071095648785,
|
||||
},
|
||||
),
|
||||
z: gFp5.FP5_ONE,
|
||||
u: gFp5.FP5_ONE,
|
||||
t: gFp5.FromUint64Array([5]uint64{4, 0, 0, 0, 0}),
|
||||
}
|
||||
)
|
||||
|
||||
func (p ECgFp5Point) Equals(rhs ECgFp5Point) bool {
|
||||
return gFp5.Equals(
|
||||
gFp5.Mul(p.u, rhs.t),
|
||||
gFp5.Mul(rhs.u, p.t),
|
||||
)
|
||||
}
|
||||
|
||||
func CanBeDecodedIntoPoint(w gFp5.Element) bool {
|
||||
// Value w can be decoded if and only if it is zero, or
|
||||
// (w^2 - a)^2 - 4*b is a quadratic residue.
|
||||
e := gFp5.Sub(gFp5.Square(w), A_ECgFp5Point)
|
||||
delta := gFp5.Sub(gFp5.Square(e), B_MUL4_ECgFp5Point)
|
||||
deltaLegendre := gFp5.Legendre(delta)
|
||||
return gFp5.IsZero(w) || deltaLegendre.IsOne()
|
||||
}
|
||||
|
||||
func (p ECgFp5Point) Encode() gFp5.Element {
|
||||
return gFp5.Mul(p.t, gFp5.InverseOrZero(p.u))
|
||||
}
|
||||
|
||||
// Attempt to decode a point from an gFp5 element
|
||||
func Decode(w gFp5.Element) (ECgFp5Point, bool) {
|
||||
// Curve equation is y^2 = x*(x^2 + a*x + b); encoded value
|
||||
// is w = y/x. Dividing by x, we get the equation:
|
||||
// x^2 - (w^2 - a)*x + b = 0
|
||||
// We solve for x and keep the solution which is not itself a
|
||||
// square (if there are solutions, exactly one of them will be
|
||||
// a square, and the other will not be a square).
|
||||
|
||||
e := gFp5.Sub(gFp5.Square(w), A_ECgFp5Point)
|
||||
delta := gFp5.Sub(gFp5.Square(e), B_MUL4_ECgFp5Point)
|
||||
r, c := gFp5.CanonicalSqrt(delta)
|
||||
if !c {
|
||||
r = gFp5.FP5_ZERO
|
||||
}
|
||||
|
||||
x1 := gFp5.Div(gFp5.Add(e, r), gFp5.FP5_TWO)
|
||||
x2 := gFp5.Div(gFp5.Sub(e, r), gFp5.FP5_TWO)
|
||||
x := x2
|
||||
|
||||
x1Legendre := gFp5.Legendre(x1)
|
||||
one := g.One()
|
||||
if !one.Equal(&x1Legendre) {
|
||||
x = x1
|
||||
}
|
||||
|
||||
// If c == true (delta is not a sqrt) then we want to get the neutral here; note that if
|
||||
// w == 0, then delta = a^2 - 4*b, which is not a square, and
|
||||
// thus we also get c == 0.
|
||||
if !c {
|
||||
x = gFp5.FP5_ZERO
|
||||
}
|
||||
z := gFp5.FP5_ONE
|
||||
u := gFp5.FP5_ONE
|
||||
if !c {
|
||||
u = gFp5.FP5_ZERO
|
||||
}
|
||||
t := w
|
||||
if !c {
|
||||
t = gFp5.FP5_ONE
|
||||
}
|
||||
|
||||
// If w == 0 then this is in fact a success.
|
||||
if c || gFp5.IsZero(w) {
|
||||
return ECgFp5Point{x: x, z: z, u: u, t: t}, true
|
||||
}
|
||||
|
||||
return ECgFp5Point{}, false
|
||||
}
|
||||
|
||||
func (p ECgFp5Point) IsNeutral() bool {
|
||||
return gFp5.IsZero(p.u)
|
||||
}
|
||||
|
||||
// General point addition. formulas are complete (no special case).
|
||||
func (p ECgFp5Point) Add(rhs ECgFp5Point) ECgFp5Point {
|
||||
// cost: 10M
|
||||
|
||||
x1 := p.x
|
||||
z1 := p.z
|
||||
u1 := p.u
|
||||
_t1 := p.t
|
||||
|
||||
x2 := rhs.x
|
||||
z2 := rhs.z
|
||||
u2 := rhs.u
|
||||
_t2 := rhs.t
|
||||
|
||||
// let t1 = x1 * x2;
|
||||
t1 := gFp5.Mul(x1, x2)
|
||||
// let t2 = z1 * z2;
|
||||
t2 := gFp5.Mul(z1, z2)
|
||||
// let t3 = u1 * u2;
|
||||
t3 := gFp5.Mul(u1, u2)
|
||||
// let t4 = _t1 * _t2;
|
||||
t4 := gFp5.Mul(_t1, _t2)
|
||||
// let t5 = (x1 + z1) * (x2 + z2) - t1 - t2;
|
||||
t5 := gFp5.Sub(
|
||||
gFp5.Mul(gFp5.Add(x1, z1), gFp5.Add(x2, z2)),
|
||||
gFp5.Add(t1, t2),
|
||||
)
|
||||
// let t6 = (u1 + _t1) * (u2 + _t2) - t3 - t4;
|
||||
t6 := gFp5.Sub(
|
||||
gFp5.Mul(gFp5.Add(u1, _t1), gFp5.Add(u2, _t2)),
|
||||
gFp5.Add(t3, t4),
|
||||
)
|
||||
// let t7 = t1 + t2 * Self::B;
|
||||
t7 := gFp5.Add(t1, gFp5.Mul(t2, B_ECgFp5Point))
|
||||
// let t8 = t4 * t7;
|
||||
t8 := gFp5.Mul(t4, t7)
|
||||
// let t9 = t3 * (t5 * Self::B_MUL2 + t7.double());
|
||||
t9 := gFp5.Mul(
|
||||
t3,
|
||||
gFp5.Add(gFp5.Mul(t5, B_MUL2_ECgFp5Point), gFp5.Double(t7)),
|
||||
)
|
||||
// let t10 = (t4 + t3.double()) * (t5 + t7);
|
||||
t10 := gFp5.Mul(
|
||||
gFp5.Add(t4, gFp5.Double(t3)),
|
||||
gFp5.Add(t5, t7),
|
||||
)
|
||||
|
||||
xNew := gFp5.Mul(gFp5.Sub(t10, t8), B_ECgFp5Point)
|
||||
zNew := gFp5.Sub(t8, t9)
|
||||
uNew := gFp5.Mul(t6, gFp5.Sub(gFp5.Mul(t2, B_ECgFp5Point), t1))
|
||||
tNew := gFp5.Add(t8, t9)
|
||||
|
||||
return ECgFp5Point{x: xNew, z: zNew, u: uNew, t: tNew}
|
||||
}
|
||||
|
||||
func (p ECgFp5Point) Double() ECgFp5Point {
|
||||
newPoint := p
|
||||
newPoint.SetDouble()
|
||||
return newPoint
|
||||
}
|
||||
|
||||
func (p *ECgFp5Point) SetDouble() {
|
||||
// cost: 4M+5S
|
||||
x := p.x
|
||||
z := p.z
|
||||
u := p.u
|
||||
t := p.t
|
||||
|
||||
t1 := gFp5.Mul(z, t)
|
||||
t2 := gFp5.Mul(t1, t)
|
||||
x1 := gFp5.Square(t2)
|
||||
z1 := gFp5.Mul(t1, u)
|
||||
t3 := gFp5.Square(u)
|
||||
w1 := gFp5.Sub(
|
||||
t2,
|
||||
gFp5.Mul(
|
||||
t3,
|
||||
gFp5.Double(gFp5.Add(x, z)),
|
||||
),
|
||||
)
|
||||
t4 := gFp5.Square(z1)
|
||||
|
||||
xNew := gFp5.Mul(t4, B_MUL4_ECgFp5Point)
|
||||
zNew := gFp5.Square(w1)
|
||||
uNew := gFp5.Sub(
|
||||
gFp5.Square(gFp5.Add(w1, z1)),
|
||||
gFp5.Add(t4, zNew),
|
||||
)
|
||||
tNew := gFp5.Sub(
|
||||
gFp5.Double(x1),
|
||||
gFp5.Add(
|
||||
gFp5.Mul(t4, gFp5.FromUint64Array([5]uint64{4, 0, 0, 0, 0})),
|
||||
zNew,
|
||||
),
|
||||
)
|
||||
|
||||
p.x = xNew
|
||||
p.z = zNew
|
||||
p.u = uNew
|
||||
p.t = tNew
|
||||
}
|
||||
|
||||
func (p *ECgFp5Point) MDouble(n uint32) ECgFp5Point {
|
||||
newPoint := ECgFp5Point{x: p.x, z: p.z, u: p.u, t: p.t}
|
||||
newPoint.SetMDouble(n)
|
||||
return newPoint
|
||||
}
|
||||
|
||||
func (p *ECgFp5Point) SetMDouble(n uint32) {
|
||||
if n == 0 {
|
||||
return
|
||||
}
|
||||
if n == 1 {
|
||||
p.SetDouble()
|
||||
return
|
||||
}
|
||||
|
||||
// cost: n*(2M+5S) + 2M+1S
|
||||
x0 := p.x
|
||||
z0 := p.z
|
||||
u0 := p.u
|
||||
t0 := p.t
|
||||
|
||||
t1 := gFp5.Mul(z0, t0)
|
||||
t2 := gFp5.Mul(t1, t0)
|
||||
x1 := gFp5.Square(t2)
|
||||
z1 := gFp5.Mul(t1, u0)
|
||||
t3 := gFp5.Square(u0)
|
||||
w1 := gFp5.Sub(
|
||||
t2,
|
||||
gFp5.Mul(
|
||||
gFp5.Double(gFp5.Add(x0, z0)),
|
||||
t3,
|
||||
),
|
||||
)
|
||||
t4 := gFp5.Square(w1)
|
||||
t5 := gFp5.Square(z1)
|
||||
x := gFp5.Mul(gFp5.Square(t5), B_MUL16_ECgFp5Point)
|
||||
w := gFp5.Sub(
|
||||
gFp5.Double(x1),
|
||||
gFp5.Add(
|
||||
gFp5.Mul(t5, gFp5.FromUint64Array([5]uint64{4, 0, 0, 0, 0})),
|
||||
t4,
|
||||
),
|
||||
)
|
||||
z := gFp5.Sub(
|
||||
gFp5.Square(gFp5.Add(w1, z1)),
|
||||
gFp5.Add(t4, t5),
|
||||
)
|
||||
|
||||
for i := 2; i < int(n); i++ {
|
||||
t1 = gFp5.Square(z)
|
||||
t2 = gFp5.Square(t1)
|
||||
t3 = gFp5.Square(w)
|
||||
t4 = gFp5.Square(t3)
|
||||
t5 = gFp5.Sub(
|
||||
gFp5.Square(gFp5.Add(w, z)),
|
||||
gFp5.Add(t1, t3),
|
||||
)
|
||||
z = gFp5.Mul(
|
||||
t5,
|
||||
gFp5.Sub(
|
||||
gFp5.Double(gFp5.Add(x, t1)),
|
||||
t3,
|
||||
),
|
||||
)
|
||||
x = gFp5.Mul(gFp5.Mul(t2, t4), B_MUL16_ECgFp5Point)
|
||||
w = gFp5.Neg(
|
||||
gFp5.Add(
|
||||
t4,
|
||||
gFp5.Mul(
|
||||
t2,
|
||||
gFp5.Sub(
|
||||
B_MUL4_ECgFp5Point,
|
||||
gFp5.FromUint64Array([5]uint64{4, 0, 0, 0, 0}),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
t1 = gFp5.Square(w)
|
||||
t2 = gFp5.Square(z)
|
||||
t3 = gFp5.Sub(
|
||||
gFp5.Square(gFp5.Add(w, z)),
|
||||
gFp5.Add(t1, t2),
|
||||
)
|
||||
w1 = gFp5.Sub(
|
||||
t1,
|
||||
gFp5.Double(gFp5.Add(x, t2)),
|
||||
)
|
||||
|
||||
p.x = gFp5.Mul(gFp5.Square(t3), B_ECgFp5Point)
|
||||
p.z = gFp5.Square(w1)
|
||||
p.u = gFp5.Mul(t3, w1)
|
||||
p.t = gFp5.Sub(
|
||||
gFp5.Mul(
|
||||
gFp5.Double(t1),
|
||||
gFp5.Sub(t1, gFp5.Double(t2)),
|
||||
),
|
||||
p.z,
|
||||
)
|
||||
}
|
||||
|
||||
// Add a point in affine coordinates to this one.
|
||||
func (p ECgFp5Point) AddAffine(rhs AffinePoint) ECgFp5Point {
|
||||
// cost: 8M
|
||||
x1, z1, u1, _t1 := p.x, p.z, p.u, p.t
|
||||
x2, u2 := rhs.x, rhs.u
|
||||
|
||||
t1 := gFp5.Mul(x1, x2)
|
||||
t2 := z1
|
||||
t3 := gFp5.Mul(u1, u2)
|
||||
t4 := _t1
|
||||
t5 := gFp5.Add(x1, gFp5.Mul(x2, z1))
|
||||
t6 := gFp5.Add(u1, gFp5.Mul(u2, _t1))
|
||||
t7 := gFp5.Add(t1, gFp5.Mul(t2, B_ECgFp5Point))
|
||||
t8 := gFp5.Mul(t4, t7)
|
||||
t9 := gFp5.Mul(t3, gFp5.Add(gFp5.Mul(t5, B_MUL2_ECgFp5Point), gFp5.Double(t7)))
|
||||
t10 := gFp5.Mul(gFp5.Add(t4, gFp5.Double(t3)), gFp5.Add(t5, t7))
|
||||
|
||||
return ECgFp5Point{
|
||||
x: gFp5.Mul(gFp5.Sub(t10, t8), B_ECgFp5Point),
|
||||
u: gFp5.Mul(t6, gFp5.Sub(gFp5.Mul(t2, B_ECgFp5Point), t1)),
|
||||
z: gFp5.Sub(t8, t9),
|
||||
t: gFp5.Add(t8, t9),
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
WINDOW = 5
|
||||
WIN_SIZE = 1 << (WINDOW - 1)
|
||||
)
|
||||
|
||||
// Convert points to affine coordinates.
|
||||
func BatchToAffine(src []ECgFp5Point) []AffinePoint {
|
||||
// We use a trick due to Montgomery: to compute the inverse of
|
||||
// x and of y, a single inversion suffices, with:
|
||||
// 1/x = y*(1/(x*y))
|
||||
// 1/y = x*(1/(x*y))
|
||||
// This extends to the case of inverting n values, with a total
|
||||
// cost of 1 inversion and 3*(n-1) multiplications.
|
||||
n := len(src)
|
||||
if n == 0 {
|
||||
return []AffinePoint{}
|
||||
}
|
||||
if n == 1 {
|
||||
p := src[0]
|
||||
m1 := gFp5.InverseOrZero(gFp5.Mul(p.z, p.t))
|
||||
return []AffinePoint{
|
||||
{
|
||||
x: gFp5.Mul(gFp5.Mul(p.x, p.t), m1),
|
||||
u: gFp5.Mul(gFp5.Mul(p.u, p.z), m1),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
res := make([]AffinePoint, n)
|
||||
// Compute product of all values to invert, and invert it.
|
||||
// We also use the x and u coordinates of the points in the
|
||||
// destination slice to keep track of the partial products.
|
||||
m := gFp5.Mul(src[0].z, src[0].t)
|
||||
for i := 1; i < n; i++ {
|
||||
x := m
|
||||
m = gFp5.Mul(m, src[i].z)
|
||||
u := m
|
||||
m = gFp5.Mul(m, src[i].t)
|
||||
|
||||
res[i] = AffinePoint{x: x, u: u}
|
||||
}
|
||||
|
||||
m = gFp5.InverseOrZero(m)
|
||||
|
||||
// Propagate back inverses.
|
||||
for i := n - 1; i > 0; i-- {
|
||||
res[i].u = gFp5.Mul(gFp5.Mul(src[i].u, res[i].u), m)
|
||||
m = gFp5.Mul(m, src[i].t)
|
||||
res[i].x = gFp5.Mul(gFp5.Mul(src[i].x, res[i].x), m)
|
||||
m = gFp5.Mul(m, src[i].z)
|
||||
}
|
||||
res[0].u = gFp5.Mul(gFp5.Mul(src[0].u, src[0].z), m)
|
||||
m = gFp5.Mul(m, src[0].t)
|
||||
res[0].x = gFp5.Mul(src[0].x, m)
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func (p ECgFp5Point) MakeWindowAffine() []AffinePoint {
|
||||
tmp := make([]ECgFp5Point, WIN_SIZE)
|
||||
tmp[0] = p
|
||||
for i := 1; i < WIN_SIZE; i++ {
|
||||
if (i & 1) == 0 {
|
||||
tmp[i] = tmp[i-1].Add(p)
|
||||
} else {
|
||||
tmp[i] = tmp[i>>1].Double()
|
||||
}
|
||||
}
|
||||
return BatchToAffine(tmp)
|
||||
}
|
||||
|
||||
// Multiply this point by a scalar.
|
||||
func (p *ECgFp5Point) SetMul(s *ECgFp5Scalar) {
|
||||
// Make a window with affine points.
|
||||
win := p.MakeWindowAffine()
|
||||
digits := make([]int32, (319+WINDOW)/WINDOW)
|
||||
s.RecodeSigned(digits, int32(WINDOW))
|
||||
|
||||
*p = LookupVarTime(win, digits[len(digits)-1]).ToPoint()
|
||||
for i := len(digits) - 2; i >= 0; i-- {
|
||||
p.SetMDouble(uint32(WINDOW))
|
||||
lookup := Lookup(win, digits[i])
|
||||
*p = p.AddAffine(lookup)
|
||||
}
|
||||
}
|
||||
|
||||
func (p ECgFp5Point) Mul(s *ECgFp5Scalar) ECgFp5Point {
|
||||
newPoint := p
|
||||
newPoint.SetMul(s)
|
||||
return newPoint
|
||||
}
|
||||
Reference in New Issue
Block a user