Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Maybe wolfe #6

Merged
merged 10 commits into from
May 10, 2024
Prev Previous commit
Next Next commit
Transition to matrices compiles
  • Loading branch information
Mikerah committed Apr 28, 2024
commit dbc4c01f347017ab22619b1d9ca5d66b903122a4
24 changes: 15 additions & 9 deletions arbitrage.mpc
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,34 @@ cfix.set_precision(f=16, k=40)
sfix.set_precision(f=16, k=40)

# Create pools
reserves_eq = sfix.Array(2)
#reserves_eq = sfix.Array(2)
reserves_eq = Matrix(2, 1, sfix)
reserves_eq.assign([1000000, 1000000])
globals_eq = Array.create_from([regint(0), regint(1)])
fee = sfix(1)
equal_pool = ProductTwoCoinCFMM(reserves_eq, fee, globals_eq)

reserves_uneq = sfix.Array(2)
reserves_uneq.assign_vector([1000, 2000])
#reserves_uneq = sfix.Array(2)
reserves_uneq = Matrix(2, 1, sfix)
reserves_uneq.assign([1000, 2000])
globals_uneq = Array.create_from([regint(0), regint(1)])
unequal_small_pool = ProductTwoCoinCFMM(reserves_uneq, fee, globals_uneq)

reserves_weighted = sfix.Array(2)
reserves_weighted.assign_vector([1000, 2000])
#reserves_weighted = sfix.Array(2)
reserves_weighted = Matrix(2, 1, sfix)
reserves_weighted.assign([1000, 2000])
globals_weighted = Array.create_from([regint(0), regint(1)])
weights = sfix.Array(2)
weights.assign_vector([0.4, 0.6])
#weights = sfix.Array(2)
weights = Matrix(2, 1, sfix)
weights.assign([0.4, 0.6])
weighted_pool = GeometricMeanTwoCoinCFMM(reserves_weighted, weights, fee, globals_weighted)

# Get market price vector
# Just get the market price of assets from a player. Will change to MPCaaS setting client later.
price_vector = sfix.Array(2)
price_vector[0], price_vector[1] = sfix.get_input_from(0, size=2)
#price_vector = sfix.Array(2)
price_vector = Matrix(2, 1, sfix)
#price_vector[0][0], price_vector[0][1] = sfix.get_input_from(0, size=2)
price_vector.assign(sfix.get_input_from(0, size=2))
#print("from arbitrage.mpc")
#print(type(price_vector[0]))
lin_obj = LinearNonnegative(price_vector)
Expand Down
49 changes: 27 additions & 22 deletions cfmms.mpc
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ from Compiler import mpc_math

class CFMM:
"""
reserves: list[sfix]
reserves: Matrix[sfix]
gamma: sfix
Ai: Array[int]
Ai: Array[regint]
"""
def __init__(self, reserves, fee, Ai):
self.R = reserves
Expand All @@ -30,17 +30,17 @@ class CFMM:


"""
price_vector: list[sfix]
reservers: list[sfix]
price_vector: Matrix[sfix]
reserves: Matrix[sfix]
invariant: sfix
fee: sfix
"""
def arb_delta(self, market_reference_price, reserve, invariant, fee):
pass

"""
price_vector: list[sfix]
reservers: list[sfix]
price_vector: Matrix[sfix]
reserves: Matrix[sfix]
invariant: sfix
fee: sfix
"""
Expand All @@ -59,12 +59,16 @@ class ProductTwoCoinCFMM(CFMM):
super().__init__(reserves, fee, Ai)

def phi(self):
return self.R[0] * self.R[1]
#print(type(self.R[0][0] * self.R[1][0]))
return self.R[0][0] * self.R[1][0]

def gradient_phi(self):
R_prime = sfix.Array(len(self.R))
R_prime[0] = self.R[1]
R_prime[1] = self.R[0]
R_prime = Matrix(len(self.R), 1, sfix)
R_prime[0][0] = self.R[0][1]
R_prime[0][1]= self.R[0][0]
#R_prime = sfix.Array(len(self.R))
#R_prime[0] = self.R[1]
#R_prime[1] = self.R[0]
return R_prime

def find_arb(self, tendered_baskets, received_baskets, price_vector):
Expand All @@ -79,11 +83,11 @@ class ProductTwoCoinCFMM(CFMM):
#print(type(tendered_baskets))
#print(type(received_baskets))
#print(type(price_vector))
tendered_baskets[0] = (self.gamma > 0).if_else(self.arb_delta(price_vector[1]/price_vector[0], self.R[0], k, self.gamma), False)
tendered_baskets[1] = (self.gamma > 0).if_else(self.arb_delta(price_vector[0]/price_vector[1], self.R[1], k, self.gamma), False)
tendered_baskets[0] = (self.gamma > 0).if_else(self.arb_delta(price_vector[1][0]/price_vector[0][0], self.R[0][0], k, self.gamma), False)
tendered_baskets[1] = (self.gamma > 0).if_else(self.arb_delta(price_vector[0][0]/price_vector[1][0], self.R[1][0], k, self.gamma), False)

received_baskets[0] = (self.gamma > 0).if_else(self.arb_lambda(price_vector[0]/price_vector[1], self.R[0], k, self.gamma), False)
received_baskets[1] = (self.gamma > 0).if_else(self.arb_lambda(price_vector[1]/price_vector[0], self.R[1], k, self.gamma), False)
received_baskets[0] = (self.gamma > 0).if_else(self.arb_lambda(price_vector[0][0]/price_vector[1][0], self.R[0][0], k, self.gamma), False)
received_baskets[1] = (self.gamma > 0).if_else(self.arb_lambda(price_vector[1][0]/price_vector[0][0], self.R[1][0], k, self.gamma), False)

# Can simply short circuit to k.reveal() == False
# Leaving for learning + demonstration purposes
Expand Down Expand Up @@ -118,9 +122,10 @@ class GeometricMeanTwoCoinCFMM(CFMM):
return (self.R[0]**self.weights[0]) * (self.R[1]**self.weights[1])

def gradient_phi(self):
R_prime = sfix.Array(len(self.R))
R_prime[0] = self.weights[0] * (self.R[1]/self.R[0])**self.weights[1]
R_prime[1] = self.weights[1] * (self.R[0]/self.R[1])**self.weights[0]
#R_prime = sfix.Array(len(self.R))
R_prime = Matrix(len(self.R), 1, sfix)
R_prime[0][0] = self.weights[0][0] * (self.R[0][1]/self.R[0][0])**self.weights[0][1]
R_prime[1][0] = self.weights[1][0] * (self.R[0][0]/self.R[1][0])**self.weights[0][0]
return R_prime

def geom_arb_delta(self, market_reference_price, reserve1, reserve2, invariant, fee):
Expand All @@ -132,13 +137,13 @@ class GeometricMeanTwoCoinCFMM(CFMM):
def find_arb(self, tendered_baskets, received_baskets, price_vector):
R = self.reserves
fee = self.fee
eta = self.weights[1]/self.weights[0]
eta = self.weights[1][0]/self.weights[0][0]

tendered_baskets[0] = self.geom_arb_delta(price_vector[1]/price_vector[0], R[1], R[0], eta, fee)
tendered_baskets[1] = self.geom_arb_delta(price_vector[0]/price_vector[1], R[0], R[1], 1/eta, fee)
tendered_baskets[0] = self.geom_arb_delta(price_vector[1][0]/price_vector[0][0], R[1][0], R[0][0], eta, fee)
tendered_baskets[1] = self.geom_arb_delta(price_vector[0][0]/price_vector[1][0], R[0][0], R[1][0], 1/eta, fee)

received_baskets[0] = self.geom_arb_lambda(price_vector[0]/price_vector[1], R[0], R[1], 1/eta, fee)
received_baskets[1] = self.geom_arb_lambda(price_vector[1]/price_vector[0], R[1], R[0], eta, fee)
received_baskets[0] = self.geom_arb_lambda(price_vector[0][0]/price_vector[1][0], R[0][0], R[1][0], 1/eta, fee)
received_baskets[1] = self.geom_arb_lambda(price_vector[1][0]/price_vector[0][0], R[1][0], R[0][0], eta, fee)

return (tendered_baskets, received_baskets)

Expand Down
64 changes: 51 additions & 13 deletions optimizers.mpc
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ class L_BFGS_BOptimizer(Optimizer):
def optimize(self, initial_guess, fn=None, g=None, memory_size=17, threshold=cfix(0.0001), alpha=MemValue(cfix(0.5)), rho=cfix(0.5), armijo_c=cfix(0.0001), c_2=cfix(0.9), n_iter=10):
k = regint(0)

#guess_k = Matrix(len(initial_guess), 1, sfix)
guess_k = Array.create_from(initial_guess)
guess_k = Matrix(len(initial_guess), 1, sfix)
#guess_k = Array.create_from(initial_guess)
guess_k.assign(initial_guess)
#print("from optimizers.mpc")
#print(type(initial_guess))
Expand Down Expand Up @@ -177,36 +177,59 @@ class L_BFGS_BOptimizer(Optimizer):
def _():
break_loop()

return (guess_k, self.function(guess_k))
return (guess_k, self.function.at(guess_k))


class LinearNonnegative:
def __init__(self, constants):
tmp = []
for i in range(len(constants)):
tmp.append((constants[i] > 0).if_else(True, False))
#tmp = []
#for i in range(len(constants)):
# tmp.append((constants[i] > 0).if_else(True, False))

for i in tmp:
if i is False:
raise Exception
#for i in tmp:
# if i is False:
# raise Exception

# NB: Probably shouldn't reveal this
runtime_error_if((constants[0][:] > 0).reveal(), "all elements must be strictly positive")

self.constants = constants
#return self.constants

def conjugate(self, v):
"""
tmp = []
for i in range(len(constants)):
tmp.append((self.constants[i][0] <= v[i][0]).if_else(True, False))

for i in tmp:
if i is False:
raise Exception
"""

tmp = Matrix(len(v), 1, sfix)
tmp.assign(v[:][0] - self.constants[:][0])

zero_vec = Matrix(len(v), 1, sfix)

@if_e((tmp[:] >= 0).reveal())
def _():
zero_vec.assign_all(0)
@else_
def _():
runtime_error("Constants must be at most coefficients in v")

#zero_vec = Matrix(len(v), 1, sfix)
zero_vec = sfix.Array(2)
return zero_vec

"""
zero_vec = Matrix(len(v), 1, sfix)
#zero_vec = sfix.Array(2)
zero_vec.assign_all(0)
return zero_vec
"""

def grad(self, v):
"""
tmp = []
@for_range(len(self.constants))
def _(i):
Expand All @@ -219,9 +242,24 @@ class LinearNonnegative:
zero_vec = Matrix(len(v), 1, sfix)
zero_vec.assign_all(0)
return zero_vec
"""

tmp = Matrix(len(v), 1, sfix)
tmp.assign(v[:][0] - self.constants[:][0])

zero_vec = Matrix(len(v), 1, sfix)

@if_e((tmp[:] >= 0).reveal())
def _():
zero_vec.assign_all(0)
@else_
def _():
runtime_error("Constants must be at most coefficients in v")

return zero_vec

#def at(self, x):
# return self.constants
def at(self, x):
return self.constants

def norm(self, x):
s = sum(self.constants)
Expand Down
6 changes: 4 additions & 2 deletions router.mpc
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,11 @@ class ArbitrageRouter:
#print(type(v[cfmm.Ai]))
tmp_big_delta = Matrix(len(big_delta), 1, sfix)
tmp_big_lambda = Matrix(len(big_lambda), 1, sfix)
accumulator += (tmp_big_lambda.dot(v[cfmm.Ai]) - tmp_big_delta.dot(v[cfmm.Ai]))
#print(type(tmp_big_lambda))
#print(type(v.get_vector_by_indices(*cfmm.Ai)))
accumulator += (tmp_big_lambda.dot(v.get_vector_by_indices(*cfmm.Ai)) - tmp_big_delta.dot(v.get_vector_by_indices(*cfmm.Ai)))

return self.linearnn_objective.conjugate(v) + accumulator
return self.linearnn_objective.conjugate(v)[:] + accumulator

def g(v):
G = Matrix(len(self.v), 1, sfix)
Expand Down