feat(core): implement core MEV bot functionality with market scanning and Uniswap V3 pricing
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
200
vendor/github.com/crate-crypto/go-ipa/ipa/barycentric.go
generated
vendored
Normal file
200
vendor/github.com/crate-crypto/go-ipa/ipa/barycentric.go
generated
vendored
Normal file
@@ -0,0 +1,200 @@
|
||||
package ipa
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/crate-crypto/go-ipa/bandersnatch/fr"
|
||||
"github.com/crate-crypto/go-ipa/common"
|
||||
)
|
||||
|
||||
// domainSize will always equal 256, which is the same
|
||||
// as the degree of the polynomial (+1), we are committing to.
|
||||
// This constant is defined here for semantic reasons.
|
||||
const domainSize = common.VectorLength
|
||||
|
||||
// PrecomputedWeights contains precomputed coefficients for efficient
|
||||
// usage of the Barycentric formula.
|
||||
type PrecomputedWeights struct {
|
||||
// This stores A'(x_i) and 1/A'(x_i)
|
||||
barycentricWeights []fr.Element
|
||||
// This stores 1/k and -1/k for k \in [0, 255]
|
||||
invertedDomain []fr.Element
|
||||
}
|
||||
|
||||
// NewPrecomputedWeights generates the precomputed weights for the barycentric formula.
|
||||
func NewPrecomputedWeights() *PrecomputedWeights {
|
||||
// Imagine we have two arrays of the same length and we concatenate them together
|
||||
// This is how we will store the A'(x_i) and 1/A'(x_i)
|
||||
// This midpoint variable is used to compute the offset that we need
|
||||
// to place 1/A'(x_i)
|
||||
midpoint := uint64(domainSize)
|
||||
|
||||
// Note there are DOMAIN_SIZE number of weights, but we are also storing their inverses
|
||||
// so we need double the amount of space
|
||||
barycentricWeights := make([]fr.Element, midpoint*2)
|
||||
for i := uint64(0); i < midpoint; i++ {
|
||||
weight := computeBarycentricWeightForElement(i)
|
||||
|
||||
var invWeight fr.Element
|
||||
invWeight.Inverse(&weight)
|
||||
|
||||
barycentricWeights[i] = weight
|
||||
barycentricWeights[i+midpoint] = invWeight
|
||||
}
|
||||
|
||||
// Computing 1/k and -1/k for k \in [0, 255]
|
||||
// Note that since we cannot do 1/0, we have one less element
|
||||
midpoint = domainSize - 1
|
||||
invertedDomain := make([]fr.Element, midpoint*2)
|
||||
for i := uint64(1); i < domainSize; i++ {
|
||||
var k fr.Element
|
||||
k.SetUint64(i)
|
||||
k.Inverse(&k)
|
||||
|
||||
var negative_k fr.Element
|
||||
zero := fr.Zero()
|
||||
negative_k.Sub(&zero, &k)
|
||||
|
||||
invertedDomain[i-1] = k
|
||||
invertedDomain[(i-1)+midpoint] = negative_k
|
||||
}
|
||||
|
||||
return &PrecomputedWeights{
|
||||
barycentricWeights: barycentricWeights,
|
||||
invertedDomain: invertedDomain,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// computes A'(x_j) where x_j must be an element in the domain
|
||||
// This is computed as the product of x_j - x_i where x_i is an element in the domain
|
||||
// and x_i is not equal to x_j
|
||||
func computeBarycentricWeightForElement(element uint64) fr.Element {
|
||||
// let domain_element_fr = Fr::from(domain_element as u128);
|
||||
if element > domainSize {
|
||||
panic(fmt.Sprintf("the domain is [0,255], %d is not in the domain", element))
|
||||
}
|
||||
|
||||
var domain_element_fr fr.Element
|
||||
domain_element_fr.SetUint64(element)
|
||||
|
||||
total := fr.One()
|
||||
|
||||
for i := uint64(0); i < domainSize; i++ {
|
||||
if i == element {
|
||||
continue
|
||||
}
|
||||
|
||||
var i_fr fr.Element
|
||||
i_fr.SetUint64(i)
|
||||
|
||||
var tmp fr.Element
|
||||
tmp.Sub(&domain_element_fr, &i_fr)
|
||||
|
||||
total.Mul(&total, &tmp)
|
||||
}
|
||||
|
||||
return total
|
||||
}
|
||||
|
||||
// ComputeBarycentricCoefficients, computes the coefficients `bary_coeffs`
|
||||
// for a point `z` such that when we have a polynomial `p` in lagrange
|
||||
// basis, the inner product of `p` and `bary_coeffs` is equal to p(z)
|
||||
// Note that `z` should not be in the domain.
|
||||
// This can also be seen as the lagrange coefficients L_i(point)
|
||||
func (preComp *PrecomputedWeights) ComputeBarycentricCoefficients(point fr.Element) []fr.Element {
|
||||
// Compute A'(x_i) * (point - x_i)
|
||||
lagrangeEvals := make([]fr.Element, domainSize)
|
||||
for i := uint64(0); i < domainSize; i++ {
|
||||
weight := preComp.barycentricWeights[i]
|
||||
|
||||
var i_fr fr.Element
|
||||
i_fr.SetUint64(i)
|
||||
lagrangeEvals[i].Sub(&point, &i_fr)
|
||||
lagrangeEvals[i].Mul(&lagrangeEvals[i], &weight)
|
||||
}
|
||||
|
||||
totalProd := fr.One()
|
||||
for i := uint64(0); i < domainSize; i++ {
|
||||
var i_fr fr.Element
|
||||
i_fr.SetUint64(i)
|
||||
|
||||
var tmp fr.Element
|
||||
tmp.Sub(&point, &i_fr)
|
||||
totalProd.Mul(&totalProd, &tmp)
|
||||
}
|
||||
|
||||
lagrangeEvals = fr.BatchInvert(lagrangeEvals)
|
||||
for i := uint64(0); i < domainSize; i++ {
|
||||
lagrangeEvals[i].Mul(&lagrangeEvals[i], &totalProd)
|
||||
}
|
||||
|
||||
return lagrangeEvals
|
||||
}
|
||||
|
||||
// DivideOnDomain computes f(x) - f(x_i) / x - x_i where x_i is an element in the domain
|
||||
func (preComp *PrecomputedWeights) DivideOnDomain(index uint8, f []fr.Element) []fr.Element {
|
||||
quotient := make([]fr.Element, domainSize)
|
||||
|
||||
y := f[index]
|
||||
|
||||
for i := 0; i < domainSize; i++ {
|
||||
if i != int(index) {
|
||||
den := i - int(index)
|
||||
absDen, is_neg := absInt(den)
|
||||
|
||||
denInv := preComp.getInvertedElement(absDen, is_neg)
|
||||
|
||||
// compute q_i
|
||||
quotient[i].Sub(&f[i], &y)
|
||||
quotient[i].Mul("ient[i], &denInv)
|
||||
|
||||
weightRatio := preComp.getRatioOfWeights(int(index), i)
|
||||
var tmp fr.Element
|
||||
tmp.Mul(&weightRatio, "ient[i])
|
||||
quotient[index].Sub("ient[index], &tmp)
|
||||
}
|
||||
}
|
||||
|
||||
return quotient
|
||||
}
|
||||
|
||||
func (preComp *PrecomputedWeights) getInvertedElement(element int, is_neg bool) fr.Element {
|
||||
index := element - 1
|
||||
|
||||
if is_neg {
|
||||
midpoint := len(preComp.invertedDomain) / 2
|
||||
index += midpoint
|
||||
}
|
||||
|
||||
return preComp.invertedDomain[index]
|
||||
}
|
||||
|
||||
func (preComp *PrecomputedWeights) getRatioOfWeights(numerator int, denominator int) fr.Element {
|
||||
|
||||
a := preComp.barycentricWeights[numerator]
|
||||
midpoint := len(preComp.barycentricWeights) / 2
|
||||
b := preComp.barycentricWeights[denominator+midpoint]
|
||||
|
||||
var result fr.Element
|
||||
result.Mul(&a, &b)
|
||||
return result
|
||||
}
|
||||
|
||||
func (preComp *PrecomputedWeights) getInverseBarycentricWeight(i int) fr.Element {
|
||||
|
||||
midpoint := len(preComp.barycentricWeights) / 2
|
||||
return preComp.barycentricWeights[i+midpoint]
|
||||
}
|
||||
|
||||
// Returns the absolute value and true if
|
||||
// the value was negative
|
||||
func absInt(x int) (int, bool) {
|
||||
is_negative := x < 0
|
||||
|
||||
if is_negative {
|
||||
return -x, is_negative
|
||||
}
|
||||
|
||||
return x, is_negative
|
||||
}
|
||||
Reference in New Issue
Block a user