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

Output Shares Don't add up #1406

Closed
ww6726 opened this issue May 15, 2024 · 9 comments
Closed

Output Shares Don't add up #1406

ww6726 opened this issue May 15, 2024 · 9 comments

Comments

@ww6726
Copy link

ww6726 commented May 15, 2024

Hi Marcel,

I am poking inside the function Popen() inside processor.hpp trying to understand how the reconstruction algorithm work.

Before program reach MC.exchange(), I manually print out all the shares as well as the MAC shares in a 3 party secario.

I try to add up those shares on paper, but found out that some of the final values are correct, while others aren't. Isn't the actual output the sum of party's share?

Thanks

@mkskeller
Copy link
Member

Please give a concrete example as well as the code and protocol you used.

@ww6726
Copy link
Author

ww6726 commented May 19, 2024

Hi Marcel,

Sure. Here is the mpc code for matrix multiplication

def run_matrix_mult(timer, repetitions, size):
    m1 = sint.Matrix(size, size)
    m2 = sint.Matrix(size, size)

    # initialize matrices

    # m1 counts from 0 to size-1
    # parallelize all assignments of values in the row (flatten)
    @for_range_parallel(size*size, [size, size])
    def _(i, j):
        m1[i][j] = 1

    # m2 is the identity matrix
    # m2.assign_all(0)
    @for_range_parallel(size*size, [size, size])
    def _(i, j):
        m2[i][j] = 1

    r = sint(size = size * size)
    @for_range(repetitions)
    def _(i):
        print_ln("Matrix mult %s, size %s", i, size)
        start_timer(timer)
        matmuls(r, m1.get_vector(), m2.get_vector(), size, size, size)

        r.reveal(0)
        stop_timer(timer)

# matrix mult
repetitions = int(program.args[1])
timer = 1
for size in program.args[2:]:
    print(repetitions, size)
    run_matrix_mult(timer, repetitions, int(size))
    timer += 1 

Here is my modified Popen found in Processor.hpp

template <class T>
void SubProcessor<T>::POpen(const Instruction& inst)
{
  //WENXUAN modification
  std::ofstream outputFileShare("Player-Data/OutputShare_"+std::to_string(P.my_num()));
  std::ofstream outputFileMAC("Player-Data/OutputMAC_"+std::to_string(P.my_num()));
  std::ofstream outputFile("Player-Data/Output_"+std::to_string(P.my_num()));

  if (inst.get_n() or BaseMachine::s().nthreads > 0)
    check();
  auto& reg = inst.get_start();
  int size = inst.get_size(); // how many output
  assert(reg.size() % 2 == 0);
  int sz=reg.size() / 2;
  MC.init_open(P, sz * size);
  for (auto it = reg.begin() + 1; it < reg.end(); it += 2){
    for (int i = 0; i < size; i++){
      MC.prepare_open(S[*it + i]);
      outputFileShare << S[*it + i].get_share() << " ";
      outputFileMAC << S[*it + i].get_mac() << " ";
    }
  }
  outputFileShare.close();
  outputFileMAC.close();
  MC.exchange(P);
  for (auto it = reg.begin(); it < reg.end(); it += 2){
    for (int i = 0; i < size; i++){
      auto res = MC.finalize_open();
      C[*it + i] = res;
      outputFile << C[*it + i] << " ";

    }
  }
  outputFile.close();
  if (inst.get_n() or BaseMachine::s().nthreads > 0)
    check();

  if (Proc != 0)
    {
      Proc->sent += sz * size;
      Proc->rounds++;
    }
}

I save each output's share as well as MAC share into files, and then I mannually aggregate them to see if they are correct.

@mkskeller
Copy link
Member

I note your using a protocol with MAC. If it based on computation modulo a power of two, note that the space of the shares is different to the cleartext space and that there is extra randomness. See for example the SPDZ2k paper: https://eprint.iacr.org/2018/482

@ww6726
Copy link
Author

ww6726 commented May 20, 2024

Oh I see. Actually my code is based on computation modulo prime 2305843009213693951. But I run the protocol with command

./lowgear-party.x -p 0 -N 3 -ip HOST -F -lgp 61 program.mpc

I thought the -lgp flag will give me the closest prime with 61 bit, hence my intended prime above. Was I using a wrong flag here?

@mkskeller
Copy link
Member

You can use -P instead of -lgp to fix the prime.

@mkskeller
Copy link
Member

Furthermore, 2305843009213693951 is unlikely to be usable with homomorphic encryption because it's not compatible with the number-theoretic transform. The prime has to 1 mod 2^15 (or a nearby power of two depending on the parameters).

@ww6726
Copy link
Author

ww6726 commented Jun 1, 2024

Hi marcel,

I am using a new prime 18446744069414584321 which is compatible with NTT. However, when I run the code with command

./lowgear-party.x -p 0 -N 3 -ip HOST -F -P 18446744069414584321  program

I obtain this error

terminate called after throwing an instance of 'prep_setup_error'
  what():  Something is wrong with the preprocessing data on disk: wrong modulus in Player-Data//3-p-64/Params-Data
Have you run the right program for generating it, such as './Fake-Offline.x 3 -lgp 64'?
Aborted

I generated triples and copy/paste to all 3 machines, but this error still exist. What am I missing here?

@mkskeller
Copy link
Member

You have to use the same -P argument with Fake-Offline.x as with lowgear-party.x.

@mkskeller mkskeller reopened this Jun 1, 2024
@ww6726
Copy link
Author

ww6726 commented Jun 3, 2024

Thank you so much !

@ww6726 ww6726 closed this as completed Jun 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants