Explorar el Código

[research/bulletproof-mpc] testing mpc ipp

ertosns hace 2 años
padre
commit
41e275b3ed

+ 99 - 0
script/research/bulletproof-mpc/expected_p.sage

@@ -0,0 +1,99 @@
+load('../mpc/curve.sage')
+load('proof.sage')
+load('transcript.sage')
+load('../mpc/beaver.sage')
+load('proof_mpc.sage')
+import gc
+##
+n = 2
+Q = to_ec_shares_list([CurvePoint.generator()])
+Q1 = to_ec_shares_list([CurvePoint.random()])
+Q2 = [q - q1 for q, q1 in zip(Q, Q1)]
+H = to_ec_shares_list([CurvePoint.generator() for i in range(0,n)])
+H1 = to_ec_shares_list([CurvePoint.random() for i in range(0,n)])
+H2 = [h - h1 for h, h1 in zip(H, H1)]
+G = to_ec_shares_list([CurvePoint.generator() for i in range(0,n)])
+G1 = to_ec_shares_list([CurvePoint.random() for i in range(0,n)])
+G2 = [g - g1 for g, g1 in zip(G, G1)]
+
+assert sum(g1.authenticated_open(g2)==CurvePoint.generator() for g1, g2 in zip(G1, G2)) == n
+
+## source
+source = Source(p)
+## alpha
+party0_val = [1, 2] # a
+party1_val = [2, 4] # b
+party0_random = [1, 1]
+alpha1 = [AuthenticatedShare(party0_random[i], source, 0) for i in range(0,n)]
+alpha2 = [AuthenticatedShare(party0_val[i] - party0_random[i], source, 0) for i in range(0,n)]
+a_shares = [alpha1, alpha2]
+
+## generators factors
+y_inv = K(1)
+G_factors = [K(1)]*n
+H_factors = [y_inv**i for i in range(0,n)]
+##
+party_0_a_prime_shares = a_shares[0].copy()
+party_1_a_prime_shares = a_shares[1].copy()
+##
+party_0_g_a_prime_shares = MSM(G1, party_0_a_prime_shares, source, 0)
+party_1_g_a_prime_shares = MSM(G2, party_1_a_prime_shares, source, 1)
+## msm multiplication shares announcement for g_a_prime_shares
+party_0_g_a_prime_shares_de = [[party_0_g_a_prime_share.d, party_0_g_a_prime_share.e] for party_0_g_a_prime_share in party_0_g_a_prime_shares.point_scalars]
+party_1_g_a_prime_shares_de = [[party_1_g_a_prime_share.d, party_1_g_a_prime_share.e] for party_1_g_a_prime_share in party_1_g_a_prime_shares.point_scalars]
+party_0_g_a_prime_shares = party_0_g_a_prime_shares.msm(party_1_g_a_prime_shares_de)
+party_1_g_a_prime_shares = party_1_g_a_prime_shares.msm(party_0_g_a_prime_shares_de)
+g_a_prime = party_0_g_a_prime_shares.authenticated_open(party_1_g_a_prime_shares)
+#a_primes = [h*a for h, a in zip(H_factors, party0_val)]
+a_primes = party0_val.copy()
+expected_g_a_prime = sum([CurvePoint.generator() * a_prime  for a_prime in a_primes])
+assert (expected_g_a_prime == g_a_prime), 'expected_g_a_prime: {}, g_a_prime: {}'.format(expected_g_a_prime, g_a_prime)
+
+## beta
+party1_random = [1, 1]
+beta1 = [AuthenticatedShare(party1_random[i], source, 1) for i in range(0,n)]
+beta2 = [AuthenticatedShare(party1_val[i] - party1_random[i], source, 1) for i in range(0,n)]
+b_shares = [beta1, beta2]
+##
+party_0_b_prime_shares = [b_share.mul_scalar(y) for b_share, y in  zip(b_shares[0], H_factors)]
+party_1_b_prime_shares = [b_share.mul_scalar(y) for b_share, y in  zip(b_shares[1], H_factors)]
+
+## c shares
+my_c_shares = [MultiplicationAuthenticatedShares(a_share, b_share, source.triplet(0), 0) for a_share, b_share in zip(a_shares[0], b_shares[0])]
+their_c_shares = [MultiplicationAuthenticatedShares(peer_a_share, peer_b_share, source.triplet(1), 1) for peer_a_share, peer_b_share in zip(a_shares[1], b_shares[1])]
+party_0_c_shares = [my_c_share.mul(their_c_share.d, their_c_share.e) for my_c_share, their_c_share in zip(my_c_shares, their_c_shares)]
+party_0_c_share = [sum_shares(party_0_c_shares, source, 0)]
+party_0_q_c_shares = MSM(Q1, party_0_c_share, source, 0)
+party_1_c_shares = [their_c_share.mul(my_c_share.d, my_c_share.e) for my_c_share, their_c_share in zip(my_c_shares, their_c_shares)]
+party_1_c_share = [sum_shares(party_1_c_shares, source, 1)]
+party_1_q_c_shares = MSM(Q2, party_1_c_share, source, 1)
+c_shares = [party_0_c_share[0].authenticated_open(party_1_c_share[0])]
+assert(c_shares[0] == sum([a*b for a,b in zip(party0_val, party1_val)])), 'sum: {}'.format(sum([a*b for a,b in zip(party0_val, party1_val)]))
+
+party_0_h_b_prime_shares = MSM(H1, party_0_b_prime_shares, source, 0)
+party_1_h_b_prime_shares = MSM(H2, party_1_b_prime_shares, source, 1)
+## msm multiplication shares announcement for g_b_prime_shares
+party_0_h_b_prime_shares_de = [[party_0_h_b_prime_share.d, party_0_h_b_prime_share.e] for party_0_h_b_prime_share in party_0_h_b_prime_shares.point_scalars]
+party_1_h_b_prime_shares_de = [[party_1_h_b_prime_share.d, party_1_h_b_prime_share.e] for party_1_h_b_prime_share in party_1_h_b_prime_shares.point_scalars]
+party_0_h_b_prime_shares = party_0_h_b_prime_shares.msm(party_1_h_b_prime_shares_de)
+party_1_h_b_prime_shares = party_1_h_b_prime_shares.msm(party_0_h_b_prime_shares_de)
+h_b_prime = party_0_h_b_prime_shares.authenticated_open(party_1_h_b_prime_shares)
+b_primes = [h*b for h, b in zip(H_factors, party1_val)]
+expected_h_b_prime = sum([CurvePoint.generator() * b_prime for b_prime in b_primes])
+assert (expected_h_b_prime == h_b_prime), 'expected_h_b_prime: {}, h_b_prime: {}'.format(expected_h_b_prime, h_b_prime)
+
+## msm multiplication shares announcement for q_c_prime_shares
+party_0_q_c_shares_de = [[party_0_q_c_share.d, party_0_q_c_share.e] for party_0_q_c_share in party_0_q_c_shares.point_scalars]
+party_1_q_c_shares_de = [[party_1_q_c_share.d, party_1_q_c_share.e] for party_1_q_c_share in party_1_q_c_shares.point_scalars]
+party_0_q_c_shares_lhs = party_0_q_c_shares.msm(party_1_q_c_shares_de)
+party_1_q_c_shares_rhs = party_1_q_c_shares.msm(party_0_q_c_shares_de)
+q_c = party_0_q_c_shares_lhs.authenticated_open(party_1_q_c_shares_rhs)
+
+## expected P
+expected_P =  sum([g_a_prime, h_b_prime, q_c])
+truth_table = [2147917197054818871619776655514917967724810669246777137580480562218260377891, 1230877877612900447137853367185807507097371113825426166020962037710421986578, 1]
+
+print('g_a_prime: {}'.format(g_a_prime))
+print('h_b_prime: {}'.format(h_b_prime))
+print('q_c: {}'.format(q_c))
+assert expected_P[0] == truth_table[0] or expected_P[1] == truth_table[1], 'P: {}, truth_Table: {}'.format(expected_P, truth_table)

+ 126 - 0
script/research/bulletproof-mpc/mpc_inner_product_proof.sage

@@ -0,0 +1,126 @@
+load('../mpc/curve.sage')
+load('proof.sage')
+load('transcript.sage')
+load('../mpc/beaver.sage')
+load('proof_mpc.sage')
+import gc
+##
+n = 2
+#Q = to_ec_shares_list([CurvePoint.generator()])
+#H = to_ec_shares_list([CurvePoint.generator() for i in range(0,n)])
+#G = to_ec_shares_list([CurvePoint.generator() for i in range(0,n)])
+Q = to_ec_shares_list([CurvePoint.generator()])
+Q1 = to_ec_shares_list([CurvePoint.random()])
+Q2 = [q - q1 for q, q1 in zip(Q, Q1)]
+H = to_ec_shares_list([CurvePoint.generator() for i in range(0,n)])
+H1 = to_ec_shares_list([CurvePoint.random() for i in range(0,n)])
+H2 = [h - h1 for h, h1 in zip(H, H1)]
+G = to_ec_shares_list([CurvePoint.generator() for i in range(0,n)])
+G1 = to_ec_shares_list([CurvePoint.random() for i in range(0,n)])
+G2 = [g - g1 for g, g1 in zip(G, G1)]
+
+## source
+source = Source(p)
+## alpha
+party0_val = [1, 2]
+party1_val = [2, 4]
+party0_random = [1,1]
+alpha1 = [AuthenticatedShare(party0_random[i], source, 0) for i in range(0,n)]
+alpha2 = [AuthenticatedShare(party0_val[i] - party0_random[i], source, 0) for i in range(0,n)]
+print('alpha2: {}'.format(alpha2))
+a_shares = [alpha1, alpha2]
+## beta
+party1_random = [1,1]
+beta1 = [AuthenticatedShare(party1_random[i], source, 1) for i in range(0,n)]
+beta2 = [AuthenticatedShare(party1_val[i] - party1_random[i], source, 1) for i in range(0,n)]
+b_shares = [beta1, beta2]
+## c
+my_c_shares = [MultiplicationAuthenticatedShares(a_share, b_share, source.triplet(0), 0) for a_share, b_share in zip(a_shares[0], b_shares[0])]
+their_c_shares = [MultiplicationAuthenticatedShares(peer_a_share, peer_b_share, source.triplet(0), 1) for peer_a_share, peer_b_share in zip(a_shares[1], b_shares[1])]
+##
+party_0_c_shares = [my_c_share.mul(their_c_share.d.copy(), their_c_share.e.copy()) for my_c_share, their_c_share in zip(my_c_shares, their_c_shares)]
+party_1_c_shares = [their_c_share.mul(my_c_share.d.copy(), my_c_share.e.copy()) for my_c_share, their_c_share in zip(my_c_shares, their_c_shares)]
+
+party_0_c_share = [sum_shares(party_0_c_shares, source, 0)]
+party_1_c_share = [sum_shares(party_1_c_shares, source, 1)]
+
+##
+y_inv = K(1)
+##
+G_factors = [K(1)]*n
+H_factors = [y_inv**i for i in range(0,n)]
+##
+party_0_b_prime_shares = [b_share.mul_scalar(y) for b_share, y in  zip(b_shares[0], H_factors)]
+party_0_a_prime_shares = a_shares[0].copy()
+##
+party_1_b_prime_shares = [b_share.mul_scalar(y) for b_share, y in  zip(b_shares[1], H_factors)]
+party_1_a_prime_shares = a_shares[1].copy()
+##
+party_0_g_a_prime_shares = MSM(G1, party_0_a_prime_shares, source, 0)
+party_0_h_b_prime_shares = MSM(H1, party_0_b_prime_shares, source, 0)
+party_0_q_c_shares = MSM(Q1, party_0_c_share, source, 0)
+##
+party_1_g_a_prime_shares = MSM(G2, party_1_a_prime_shares, source, 1)
+party_1_h_b_prime_shares = MSM(H2, party_1_b_prime_shares, source, 1)
+party_1_q_c_shares = MSM(Q2, party_1_c_share, source, 1)
+## msm multiplication shares announcement for g_a_prime_shares
+party_0_g_a_prime_shares_de = [[party_0_g_a_prime_share.d, party_0_g_a_prime_share.e] for party_0_g_a_prime_share in party_0_g_a_prime_shares.point_scalars]
+party_1_g_a_prime_shares_de = [[party_1_g_a_prime_share.d, party_1_g_a_prime_share.e] for party_1_g_a_prime_share in party_1_g_a_prime_shares.point_scalars]
+party_0_g_a_prime_shares_lhs = party_0_g_a_prime_shares.msm(party_1_g_a_prime_shares_de)
+party_1_g_a_prime_shares_rhs = party_1_g_a_prime_shares.msm(party_0_g_a_prime_shares_de)
+g_a_prime = party_0_g_a_prime_shares_lhs.authenticated_open(party_1_g_a_prime_shares_rhs)
+## msm multiplication shares announcement for g_b_prime_shares
+party_0_h_b_prime_shares_de = [[party_0_h_b_prime_share.d, party_0_h_b_prime_share.e] for party_0_h_b_prime_share in party_0_h_b_prime_shares.point_scalars]
+party_1_h_b_prime_shares_de = [[party_1_h_b_prime_share.d, party_1_h_b_prime_share.e] for party_1_h_b_prime_share in party_1_h_b_prime_shares.point_scalars]
+party_0_h_b_prime_shares_lhs = party_0_h_b_prime_shares.msm(party_1_h_b_prime_shares_de)
+party_1_h_b_prime_shares_rhs = party_1_h_b_prime_shares.msm(party_0_h_b_prime_shares_de)
+h_b_prime = party_0_h_b_prime_shares_lhs.authenticated_open(party_1_h_b_prime_shares_rhs)
+## msm multiplication shares announcement for q_c_prime_shares
+party_0_q_c_shares_de = [[party_0_q_c_share.d, party_0_q_c_share.e] for party_0_q_c_share in party_0_q_c_shares.point_scalars]
+party_1_q_c_shares_de = [[party_1_q_c_share.d, party_1_q_c_share.e] for party_1_q_c_share in party_1_q_c_shares.point_scalars]
+party_0_q_c_shares_lhs = party_0_q_c_shares.msm(party_1_q_c_shares_de)
+party_1_q_c_shares_rhs = party_1_q_c_shares.msm(party_0_q_c_shares_de)
+q_c = party_0_q_c_shares_lhs.authenticated_open(party_1_q_c_shares_rhs)
+## party 0 proof generation
+party_0_transcript = Transcript('bulletproof')
+party_0_proof = MpcProof(party_0_transcript, Q1, G_factors, H_factors, G1, H1, a_shares[0], b_shares[0], source, 0)
+## party 1 proof generation
+party_1_transcript = Transcript('bulletproof')
+party_1_proof = MpcProof(party_1_transcript, Q2, G_factors, H_factors, G2, H2, a_shares[1], b_shares[1], source, 1)
+## create proof L, R
+party_1_proof_c_l = party_1_proof.c_l.copy()
+party_1_proof_c_r = party_1_proof.c_r.copy()
+party_0_proof_c_l = party_0_proof.c_l.copy()
+party_0_proof_c_r = party_0_proof.c_r.copy()
+
+party_0_proof.create(party_1_proof_c_l, party_1_proof_c_r)
+party_1_proof.create(party_0_proof_c_l, party_0_proof_c_r)
+## expected P
+expected_P =  sum([g_a_prime, h_b_prime, q_c])
+## party 0 proof verification
+party_0_verifier = Transcript('bulletproof')
+party_0_proof.calculate_c_shares(n, party_0_verifier, G_factors, H_factors)
+## party 1 proof verification
+party_1_verifier = Transcript('bulletproof')
+party_1_proof.calculate_c_shares(n, party_1_verifier, G_factors, H_factors)
+##
+party_0_c_shares_de = [[my_c_share.d.copy(), my_c_share.e.copy()] for my_c_share in party_0_proof.my_c_shares]
+party_1_c_shares_de = [[my_c_share.d.copy(), my_c_share.e.copy()] for my_c_share in party_1_proof.my_c_shares]
+##
+party_1_proof_lhs = [[ii.copy() for ii in i] for i in party_1_proof.lhs]
+party_0_proof_lhs = [[ii.copy() for ii in i] for i in party_0_proof.lhs]
+party_1_proof_rhs = [[ii.copy() for ii in i] for i in party_1_proof.rhs]
+party_0_proof_rhs = [[ii.copy() for ii in i] for i in party_0_proof.rhs]
+# verify party 1 lpr
+party_0_proof.open_lr(Q1, G1, H1, party_1_c_shares_de ,party_1_proof_lhs, party_1_proof_rhs)
+##
+# verify party 0 lpr
+party_1_proof.open_lr(Q2, G2, H2, party_0_c_shares_de, party_0_proof_lhs, party_0_proof_rhs)
+##
+party_0_proof_l = party_0_proof.L
+party_1_proof_l = party_1_proof.L
+
+L = sum(party_0_proof_l_i.authenticated_open(party_1_proof_l_i) for party_0_proof_l_i, party_1_proof_l_i in zip(party_0_proof_l, party_1_proof_l))
+party_0_proof_r = party_0_proof.R
+party_1_proof_r = party_1_proof.R
+R = sum(party_0_proof_r_i.authenticated_open(party_1_proof_r_i) for party_0_proof_r_i, party_1_proof_r_i in zip(party_0_proof_r, party_1_proof_r))

+ 270 - 0
script/research/bulletproof-mpc/proof_mpc.sage

@@ -0,0 +1,270 @@
+'''
+bulletproof protocol 2 with multi-exponentiation.
+'''
+load('../mpc/curve.sage')
+load('../mpc/ec_share.sage')
+load('../mpc/share.sage')
+load('../mpc/beaver.sage')
+load('utils.sage')
+
+class MpcProof(object):
+      def __init__(self, transcript, Q, G_factors, H_factors, G, H, a_shares, b_shares, source, party_id):
+          '''
+          create inner product proof
+          '''
+          self.n = len(G)
+          self.m = self.n
+          assert (self.n == len(H) == len(H_factors) == len(a_shares) == len(b_shares))
+          self.source = source
+          self.party_id=party_id
+          self.Q = Q
+          self.G = G
+          self.H = H
+          self.G_factors = G_factors
+          self.H_factors = H_factors
+          self.transcript = transcript
+          self.L = []
+          self.R = []
+          L_l = []
+          R_l = []
+          self.c_l = []
+          self.c_r = []
+          self.a_shares_l = []
+          self.a_shares_r = []
+          self.b_shares_l = []
+          self.b_shares_r = []
+          self.G_hist = []
+          self.H_hist = []
+          if self.n!=1:
+                self.n /=2
+                a_shares_l, a_shares_r = a_shares[0:self.n], a_shares[self.n:]
+                b_shares_l, b_shares_r = b_shares[0:self.n], b_shares[self.n:]
+                self.a_shares_l += [a_shares_l.copy()]
+                self.a_shares_r += [a_shares_r.copy()]
+                self.b_shares_l += [b_shares_l.copy()]
+                self.b_shares_r += [b_shares_r.copy()]
+                G_l, G_r = G[0:self.n], G[self.n:]
+                H_l, H_r = H[0:self.n], H[self.n:]
+                self.G_hist+=[[G_l, G_r]]
+                self.H_hist+=[[H_l, H_r]]
+                # authenticated inner product
+                #TODO multiplication
+                c_shares_l = [MultiplicationAuthenticatedShares(a_share, b_share, self.source.triplet(self.party_id), self.party_id) for a_share, b_share in zip(a_shares_l, b_shares_r)]
+                c_shares_r = [MultiplicationAuthenticatedShares(a_share, b_share, self.source.triplet(self.party_id), self.party_id) for a_share, b_share in zip(a_shares_r, b_shares_l)]
+                self.c_l += [c_shares_l]
+                self.c_r += [c_shares_r]
+                u = K(1)
+                u_inv = 1/u
+
+                for i in range(self.n):
+                    # a_prime
+                    a_shares_l[i] = a_shares_l[i].mul_scalar(u) +  a_shares_r[i].mul_scalar(u_inv)
+                    # p_prime
+                    b_shares_l[i] = b_shares_l[i].mul_scalar(u_inv) + b_shares_r[i].mul_scalar(u)
+                    #TODO (research) get pt from share.
+                    # G_prime
+                    G_l[i] = to_ec_shares(CurvePoint.msm([G_l[i].share, G_r[i].share], [u_inv * G_factors[i], u * G_factors[self.n+i]]))
+                    # H_prime
+                    H_l[i] = to_ec_shares(CurvePoint.msm([H_l[i].share, H_r[i].share], [u * H_factors[i], u_inv * H_factors[self.n+i]]))
+
+                a_shares = a_shares_l # a is a_prime
+                b_shares = b_shares_l # b is b_prime
+                G = G_l # G is G_prime
+                H = H_l # H is H_prime
+
+          while self.n!=1:
+                self.n /=2
+                a_shares_l, a_shares_r = a_shares[0:self.n], a_shares[self.n:] # a_prime_l, a_prime_r
+                b_shares_l, b_shares_r = b_shares[0:self.n], b_shares[self.n:] # b_prime_l, b_prime_r
+                self.a_shares_l += [a_shares_l.copy()]
+                self.a_shares_r += [a_shares_r.copy()]
+                self.b_shares_l += [b_shares_l.copy()]
+                self.b_shares_r += [b_shares_r.copy()]
+                G_l, G_r = G[0:self.n], G[self.n:] # G_prime_l, G_prime_r
+                H_l, H_r = H[0:self.n], H[self.n:] # H_prime_l, H_prime_r
+                self.G_hist+=[[G_l, G_r]]
+                self.H_hist+=[[H_l, H_r]]
+                c_shares_l = [MultiplicationAuthenticatedShares(a_share, b_share, self.source.triplet(self.party_id), self.party_id) for (a_share,b_share) in zip(a_shares_l, b_shares_r)] # c_prime_l
+                c_shares_r = [MultiplicationAuthenticatedShares(a_share, b_share, self.source.triplet(self.party_id), self.party_id) for (a_share,b_share) in zip(a_shares_r, b_shares_l)] # c_prime_r
+                self.c_l += [c_shares_l]
+                self.c_r += [c_shares_r]
+                u = K(1)
+                u_inv = 1/u
+                for i in range(self.n):
+                    # u * a_prime_l + u^{-1} * a_prime_r
+                    a_shares_l[i] = a_shares_l[i].mul_scalar(u) + a_shares_r[i].mul_scalar(u_inv)
+                    # u^{-1} * b_prime_l + u * b_prime_r
+                    b_shares_l[i] = b_shares_l[i].mul_scalar(u_inv) + b_shares_r[i].mul_scalar(u)
+                    # G_l_prime
+                    G_l[i] = to_ec_shares(CurvePoint.msm([G_l[i].share, G_r[i].share], [u_inv, u]))
+                    # H_l_prime
+                    H_l[i] = to_ec_shares(CurvePoint.msm([H_l[i].share, H_r[i].share], [u, u_inv]))
+                a_shares = a_shares_l
+                b_shares = b_shares_l
+                G = G_l
+                H = H_l
+          self.a_shares = a_shares[0]
+          self.b_shares = b_shares[0]
+          self.G = G
+          self.H = H
+
+      def create(self, their_c_l_shares, their_c_r_shares):
+          '''
+          create inner product proof
+          '''
+
+          self.c_l = [[my_c_l[i].mul(their_c_l[i].d, their_c_l[i].e) for i in range(len(my_c_l))] for my_c_l, their_c_l in zip(self.c_l, their_c_l_shares)]
+          self.c_r = [[my_c_r[i].mul(their_c_r[i].d, their_c_r[i].e) for i in range(len(my_c_r))] for my_c_r, their_c_r in zip(self.c_r, their_c_r_shares)]
+
+          print('c_l: {}'.format(self.c_l))
+          print('c_r: {}'.format(self.c_r))
+          print('c: {}'.format(sum([c_l[i].authenticated_open(c_r[i]) for i in range(len(self.c_l[0])) for c_l, c_r in zip(self.c_l, self.c_r)])))
+          # create L,R for proof validation
+          L_l = []
+          R_l = []
+          counter = 0
+          if self.m!=1:
+                self.m /= 2
+                al_share_g = [al_share.mul_scalar(g) for al_share, g in zip(self.a_shares_l[counter], self.G_factors[self.m:2*self.m])]
+                br_share_h = [br_share.mul_scalar(h) for br_share, h in zip(self.b_shares_r[counter], self.H_factors[0:self.m])]
+                L_gr_al_g_share = MSM(self.G_hist[counter][1], al_share_g, self.source, self.party_id)
+                L_hl_br_h_share = MSM(self.H_hist[counter][0], br_share_h, self.source, self.party_id)
+                L_q_cl_share = MSM(self.Q, self.c_l[counter], self.source, self.party_id)
+                # L, R
+                # note that P  = L*R
+                L_shares = [L_gr_al_g_share, L_hl_br_h_share , L_q_cl_share]
+
+                ar_share_g = [ar_share.mul_scalar(g) for ar_share, g in zip(self.a_shares_r[counter], G_factors[0:self.m])]
+                bl_share_g = [bl_share.mul_scalar(h) for bl_share, h in zip(self.b_shares_l[counter], H_factors[self.m:2*self.m])]
+                R_gl_ar_g_share = MSM(self.G_hist[counter][0], ar_share_g, self.source, self.party_id)
+                R_hr_bl_h_share = MSM(self.H_hist[counter][1], bl_share_g, self.source, self.party_id)
+                R_q_cr_share = MSM(Q, self.c_r[counter], self.source, self.party_id)
+                R_shares = [R_gl_ar_g_share, R_hr_bl_h_share, R_q_cr_share]
+                L_l += [L_shares]
+                R_l += [R_shares]
+
+                counter +=1
+          while self.m!=1:
+                self.m /=2
+                # L_prime
+                L_gr_al_share = MSM(self.G_hist[counter][1], self.a_shares_l[counter], self.source, self.party_id)
+                L_hl_br_share = MSM(self.H_hist[counter][0], self.b_shares_r[counter], self.source, self.party_id)
+                L_q_cl_share = MSM(self.Q, self.c_l[counter], self.source, self.party_id)
+                L_shares = [L_gr_al_share, L_hl_br_share, L_q_cl_share]
+
+                # R_prime
+                R_gl_ar_share = MSM(self.G_hist[counter][0], a_shares_r, self.source, self.party_id)
+                R_hr_bl_share = MSM(self.H_hist[counter][1], b_shares_l, self.source, self.party_id)
+                R_q_cr_share = MSM(Q, self.c_r[counter], self.source, self.party_id)
+                R_shares = [R_gl_ar_share, R_hr_bl_share, R_q_cr_share]
+
+                L_l += [L_shares]
+                R_l += [R_shares]
+
+                counter +=1
+          #
+          self.lhs = L_l
+          self.rhs = R_l
+
+      def challenges(self, n, verifier):
+          challenges = []
+          challenges_inv = []
+          lg_n = len(self.lhs)
+          for L, R in zip(self.lhs, self.rhs):
+              #verifier.append_message(b'L', bytes(''.join([l.__str__() for l in [L]]), encoding='utf-8'))
+              #verifier.append_message(b'R', bytes(''.join([r.__str__() for r in [R]]), encoding='utf-8'))
+              #u = K(verifier.challenge_bytes(b'u'))
+              u = K(1)
+              u_inv = 1/u
+              challenges += [u]
+              challenges_inv += [u_inv]
+          inv_prod = K(1)
+          for u_inv in challenges_inv:
+              inv_prod *=K(1)
+          challenges_sq = [i*i for i in challenges]
+          challenges_inv_sq = [i*i for i in challenges_inv]
+          mul_inv = K(1)
+          for i in challenges_inv:
+              mul_inv *=i
+          S = [mul_inv]
+          for i in range(1,n):
+              lg_i = 32 - 1 - countZeros(i)
+              k = 1 << lg_i
+              u_lg_i_sq = challenges_sq[(lg_n -1) - lg_i]
+              S += [S[i-k] * u_lg_i_sq]
+          return challenges_sq, challenges_inv_sq, S
+
+      def calculate_c_shares(self, n, verifier, G_factors, H_factors):
+          self.u_sq, self.u_inv_sq, self.s = self.challenges(n, verifier)
+          self.gas_shares = [self.a_shares.mul_scalar(s_i * g_i) for g_i, s_i in zip(G_factors, self.s)][:n]
+          # inverse of count is reverse
+          self.inv_s = reversed(self.s)
+          self.hbs_shares = [self.b_shares.mul_scalar(s_i_inv * h_i) for h_i, s_i_inv in zip(H_factors, self.inv_s)]
+          #TODO (fix) this should be shares, this  is fake shares!
+          self.neg_u_sq = [i*K(-1) for i in self.u_sq]
+          self.neg_u_inv_sq = [i*K(-1) for i in self.u_inv_sq]
+          # P
+          ## u^c
+          self.my_c_shares = [MultiplicationAuthenticatedShares(a_share, b_share, self.source.triplet(self.party_id), self.party_id) for a_share, b_share in zip([self.a_shares], [self.b_shares])]
+
+      def open_lr(self, Q, G, H, their_c_shares_de, peer_lhs, peer_rhs):
+          c_shares = [my_c_share.mul(their_c_shares_de[i][0], their_c_shares_de[i][1]) for i, my_c_share in enumerate(self.my_c_shares)]
+
+          self.res_p_1 = MSM(Q, c_shares, self.source, self.party_id)
+          ## g^{g_factor_a_s}
+          self.res_p_2 = MSM(G, self.gas_shares, self.source, self.party_id)
+          ## h^{h_factor_b_s}
+          self.res_p_3 = MSM(H, self.hbs_shares, self.source, self.party_id)
+          ## L
+          for my_lhs, their_lhs in zip(self.lhs, peer_lhs):
+                L_triad = []
+                for my_lhs_i, their_lhs_i in zip(my_lhs, their_lhs):
+                      my_lhs_i_de = [[ps.d, ps.e] for ps in my_lhs_i.point_scalars]
+                      #print("lhs point scalars: {}".format(their_lhs_i.point_scalars))
+                      their_lhs_i_de = [[ps.d, ps.e] for ps in their_lhs_i.point_scalars]
+                      #my_lhs_i_share = my_lhs_i.msm(their_lhs_i_de)
+                      #their_rhs_i_share = their_lhs_i.msm(my_lhs_i_de)
+                      #L_triad  += [ECAuthenticatedShare(my_lhs_i_share.authenticated_open(their_rhs_i_share))]
+                      #L_triad += [lhs_i]
+                      lhs_i_share = my_lhs_i.msm(their_lhs_i_de)
+                      #L_triad  += [ECAuthenticatedShare(my_lhs_i_share.authenticated_open(their_rhs_i_share))]
+                      L_triad += [lhs_i_share]
+                #L += [sum_shares(L_triad, self.source, self.party_id)]
+                self.L += [sum_shares(L_triad, self.source, self.party_id)]
+          ## R
+          for my_rhs, their_rhs in zip(self.rhs, peer_rhs):
+                R_triad = []
+                for my_rhs_i, their_rhs_i in zip(my_rhs, their_rhs):
+                      my_rhs_i_de = [[ps.d, ps.e] for ps in my_rhs_i.point_scalars]
+                      their_rhs_i_de = [[ps.d, ps.e] for ps in their_rhs_i.point_scalars]
+                      #my_rhs_i_share = my_rhs_i.msm(their_rhs_i_de)
+                      #their_rhs_i_share = their_rhs_i.msm(my_rhs_i_de)
+                      #R_triad  += [ECAuthenticatedShare(my_lhs_i_share.authenticated_open(their_rhs_i_share))]
+                      rhs_i_share = my_rhs_i.msm(their_rhs_i_de)
+                      R_triad += [rhs_i_share]
+                      #R_triad += [rhs_i]
+                #R += [sum_shares(R_triad, self.source, self.party_id)]
+                self.R += [sum_shares(R_triad, self.source, self.party_id)]
+          # L^(u^2)
+          #temp = K(random.randint(0,p))
+          temp = K(0)
+          self.res_p_4 = MSM(self.L, [AuthenticatedShare(temp, self.source, self.party_id) if self.party_id==0 else AuthenticatedShare(neg_u_sq_i-temp, self.source, self.party_id) for neg_u_sq_i in self.neg_u_sq], self.source, self.party_id)
+          # R^(u^-2)
+          self.res_p_5 = MSM(self.R, [AuthenticatedShare(temp, self.source, self.party_id) if self.party_id==0 else AuthenticatedShare(neg_u_inv_sq_i-temp, self.source, self.party_id) for neg_u_inv_sq_i in self.neg_u_inv_sq], self.source, self.party_id)
+          # P prime  = L^{u^2} * P * R^{u^{-1}}
+          self.res_p = [self.res_p_1, self.res_p_2, self.res_p_3, self.res_p_4, self.res_p_5]
+
+      def open_and_validate_P(self, res_p, P):
+          P_msm_parts = []
+          for my_res_p, their_res_p in zip(self.res_p, res_p):
+                my_res_de = [[ps.d, ps.e] for ps in my_res_p.point_scalars]
+                their_res_de = [[ps.d, ps.e] for ps in their_res_p.point_scalars]
+                lhs = my_res_p.msm(their_res_de)
+                rhs = their_res_p.msm(my_res_de)
+                p_part = lhs.authenticated_open(rhs)
+                print('p_part: {}'.format(p_part))
+                P_msm_parts += [p_part]
+
+          # P prime == H(u^{-1} * a_prime_r, u * a_prime_l, u * b_prime_r, u ^ {-1} * b_prime_l, c_prime)
+          my_P = sum(P_msm_parts)
+          assert (my_P == P), 'P: {}, expected: {}'.format(my_P, P)

+ 29 - 0
script/research/bulletproof-mpc/test_inner_product.sage

@@ -0,0 +1,29 @@
+load('proof.sage')
+load('transcript.sage')
+
+n = 2
+Q = [CurvePoint.generator()*1]
+H = [CurvePoint.generator()*1 for i in range(0,n)]
+G = [CurvePoint.generator()*1 for i in range(0,n)]
+
+a = [1, 2]
+b = [2, 4]
+c = [sum([a*b for a, b in zip(a, b)])]
+y_inv = K(1)
+G_factors = [K(1)]*n
+H_factors = [y_inv**i for i in range(0,n)]
+
+b_prime = [b*y for b, y in  zip(b, H_factors)]
+a_prime = a.copy()
+
+transcript = Transcript('bulletproof')
+
+proof = Proof(transcript, Q, G_factors, H_factors, G, H, a, b)
+ga_prime = CurvePoint.msm(G, a_prime)
+print('ga_prime: {}'.format(ga_prime))
+hb_prime = CurvePoint.msm(H, b_prime)
+qc = CurvePoint.msm(Q, c)
+P_res =  sum([ga_prime, hb_prime, qc])
+print('P_res: {}'.format(P_res))
+verifier = Transcript('bulletproof')
+pp, p, _ = proof.verify(n, verifier, G_factors, H_factors, P_res, Q, G, H)