feat: 添加 Lighter 适配器及相关功能,支持 trailing stops 和新的交易逻辑

This commit is contained in:
discountry
2025-09-30 22:08:05 +08:00
parent e83bdfccf9
commit c8b0ab1c8e
101 changed files with 90621 additions and 3 deletions
@@ -0,0 +1,145 @@
package signature
import (
"fmt"
curve "github.com/elliottech/poseidon_crypto/curve/ecgfp5"
g "github.com/elliottech/poseidon_crypto/field/goldilocks"
gFp5 "github.com/elliottech/poseidon_crypto/field/goldilocks_quintic_extension"
p2 "github.com/elliottech/poseidon_crypto/hash/poseidon2_goldilocks"
)
type Signature struct {
S curve.ECgFp5Scalar
E curve.ECgFp5Scalar
}
type NumericalSignature [10]uint64
func (s Signature) ToNumericalSignature() NumericalSignature {
return NumericalSignature{
s.S[0], s.S[1], s.S[2], s.S[3], s.S[4],
s.E[0], s.E[1], s.E[2], s.E[3], s.E[4],
}
}
func (s Signature) DeepCopy() Signature {
return Signature{
S: s.S.DeepCopy(),
E: s.E.DeepCopy(),
}
}
// (s little endian) || (e little endian)
func (s Signature) ToBytes() []byte {
sBytes := s.S.ToLittleEndianBytes()
eBytes := s.E.ToLittleEndianBytes()
res := make([]byte, 80)
copy(res[:40], sBytes[:])
copy(res[40:], eBytes[:])
return res
}
func SigFromBytes(b []byte) (Signature, error) {
if len(b) != 80 {
return ZERO_SIG, fmt.Errorf("signature length should be 80 but is %d", len(b))
}
return Signature{
S: curve.ScalarElementFromLittleEndianBytes(b[:40]),
E: curve.ScalarElementFromLittleEndianBytes(b[40:]),
}, nil
}
var ZERO_SIG = Signature{
S: curve.ZERO,
E: curve.ZERO,
}
var ONE_SK = curve.ONE
// Public key is actually an EC point (4 Fp5 elements), but it can be encoded as a single Fp5 element.
func SchnorrPkFromSk(sk curve.ECgFp5Scalar) gFp5.Element {
return curve.GENERATOR_ECgFp5Point.Mul(&sk).Encode()
}
func SchnorrSignHashedMessage(hashedMsg gFp5.Element, sk curve.ECgFp5Scalar) Signature {
// Sample random scalar `k` and compute `r = k * G`
k := curve.SampleScalarCrypto()
r := curve.GENERATOR_ECgFp5Point.Mul(&k).Encode()
// Compute `e = H(r || H(m))`, which is a scalar point
preImage := make([]g.Element, 5+5)
for i, elem := range r.ToBasefieldArray() {
preImage[i] = elem
}
for i, elem := range hashedMsg.ToBasefieldArray() {
preImage[i+5] = elem
}
e := curve.FromGfp5(p2.HashToQuinticExtension(preImage))
return Signature{
S: k.Sub(*e.Mul(&sk)),
E: e,
}
}
func SchnorrSignHashedMessage2(hashedMsg gFp5.Element, sk, k curve.ECgFp5Scalar) Signature {
r := curve.GENERATOR_ECgFp5Point.Mul(&k).Encode()
// Compute `e = H(r || H(m))`, which is a scalar point
preImage := make([]g.Element, 5+5)
for i, elem := range r.ToBasefieldArray() {
preImage[i] = elem
}
for i, elem := range hashedMsg.ToBasefieldArray() {
preImage[i+5] = elem
}
e := curve.FromGfp5(p2.HashToQuinticExtension(preImage))
return Signature{
S: k.Sub(*e.Mul(&sk)),
E: e,
}
}
func Validate(pubKey, hashedMsg, sig []byte) error {
pk, err := gFp5.FromCanonicalLittleEndianBytes(pubKey)
if err != nil {
return fmt.Errorf("failed to convert public key bytes to field element: %w", err)
}
hashedMsgElem, err := gFp5.FromCanonicalLittleEndianBytes(hashedMsg)
if err != nil {
return fmt.Errorf("failed to convert hashed message bytes to field element: %w", err)
}
s, err := SigFromBytes(sig)
if err != nil {
return fmt.Errorf("failed to convert signature bytes to Schnorr signature: %w", err)
}
valid := IsSchnorrSignatureValid(&pk, &hashedMsgElem, s)
if !valid {
return fmt.Errorf("signature is invalid")
}
return nil
}
func IsSchnorrSignatureValid(pubKey, hashedMsg *gFp5.Element, sig Signature) bool {
pubKeyWs, ok := curve.DecodeFp5AsWeierstrass(*pubKey)
if !ok {
return false
}
rV := curve.MulAdd2(curve.GENERATOR_WEIERSTRASS, pubKeyWs, sig.S, sig.E).Encode() // r_v = s*G + e*pk
preImage := make([]g.Element, 5+5)
for i, elem := range rV.ToBasefieldArray() {
preImage[i] = elem
}
for i, elem := range hashedMsg.ToBasefieldArray() {
preImage[i+5] = elem
}
eV := curve.FromGfp5(p2.HashToQuinticExtension(preImage))
return eV.Equals(&sig.E) // e_v == e
}