data61 / MP-SPDZ

Versatile framework for multi-party computation
Other
900 stars 278 forks source link

I/O in Low-Level Interface #547

Closed ghoshbishakh closed 2 years ago

ghoshbishakh commented 2 years ago

I have been looking into the Low-Level Interface trying to implement a protocol of my own similar to ECDSA.

How do take input (e.g. private input from a file) using the low-level interface?

SubProcessor has Input extended from InputBase. But I am not sure how to use it. The input output documentation (https://mp-spdz.readthedocs.io/en/latest/io.html) seems to be about the high-level interface only.

mkskeller commented 2 years ago

For file operations, the basic types (such as gfp) have input and output functions. The Input class is used for inputs to the protocol, i.e., secret sharing.

ghoshbishakh commented 2 years ago

@mkskeller thanks a lot! I have been trying to use the Input class for a while. Is there any documentation (or any example where it is used)? I am using it like the following but getting segmentation faults at add_mine. Not sure what I am missing.

image

    typename pShare::Input inputProtocol(&proc, proc.P);

    inputProtocol.reset_all(proc.P);

    P256Element::Scalar randscalar;
    randscalar.randomize(G);

    cout << randscalar << endl;

    for (int i = 0; i < N.num_players(); i++){
        cout << "inputting for player " << i << endl;
        if (i == N.my_num()){
            cout << "calling add_mine " << i << endl;
            inputProtocol.add_mine(randscalar);
            }
        else {
            cout << "calling add_other " << i << endl;
            inputProtocol.add_other(i);
            }
    }
    cout << "input exchange " << endl;
    inputProtocol.exchange();
mkskeller commented 2 years ago

The interface is documented here, and there is an example here.

Can you post the complete backtrace?

mkskeller commented 2 years ago

Also note that using ProtocolSet instead of protocol instances directly should be safer.

ghoshbishakh commented 2 years ago

@mkskeller Thank you for the pointers! Really appreciate your help.

I added the following lines, and the input works, but after that, the rest of the ECDSA code (untouched) fails in the preprocessing step saying mac_fail:

    int prime_length = P256Element::Scalar::length();

    ProtocolSetup<pShare> setup(P, prime_length);

    ProtocolSet<pShare> set(P, setup);
    auto& inputProtocol = set.input;

    inputProtocol.reset_all(P);
    for (int i = 0; i < N.num_players(); i++)
        inputProtocol.add_from_all(i);
    inputProtocol.exchange();

Link to the whole code: https://github.com/ghoshbishakh/MP-SPDZ/blob/pciecdsa/ECDSA/ot-ecdsa-party.hpp#L177

I can guess that we need to make it consistent somehow, by using ProtocolSet in the rest of the code.

The ECDSA code uses SubProcessor<pShare> proc(_, MCp, prep, P); followed by auto& protocol = proc.protocol; What is the role of SubProcessor usually?

Can we use ProtocolSet instead?

mkskeller commented 2 years ago

The ECDSA is older than ProtocolSet. You should be able to replace the protocol variable of SubProcessor by the protocol variable of ProtocolSet. SubProcessor is where all information for one computation domain and one thread in the virtual machine come together. It has grown over time and isn't that easy to use, so it's better to use ProtocolSet, which also holds an instance of all core protocols.

ghoshbishakh commented 2 years ago

@mkskeller thank you again for your help and patience. I have been trying to use ProtocolSet for ECDSA.

I have used the following to generate sk which works but a lot slower than the original version.

https://github.com/ghoshbishakh/MP-SPDZ/blob/8301f6ed4ee3cc94d8650645c716374a9212f8f5/ECDSA/ot-ecdsa-party.hpp#L112-L132

    // Protocol Set
    ProtocolSetup<pShare> protocolSetup(P, prime_length);
    ProtocolSet<pShare> protocolSet(P, protocolSetup);

    OnlineOptions::singleton.batch_size = 1;

    pShare sk, __;
    // synchronize
    Bundle<octetStream> bundle(P);
    P.unchecked_broadcast(bundle);
    Timer timer;
    timer.start();
    auto stats = P.total_comm();
    protocolSet.preprocessing.get_two(DATA_INVERSE, sk, __);
    cout << "Secret key generation took " << timer.elapsed() * 1e3 << " ms" << endl;

After this, in the preprocessing step, I am getting mac_fail I am trying to use auto& MCp = protocolSet.processor.MC and then using MCc.POpen_Begin, MCc.POpen_End, MCc.Check(extra_player).

Should I do anything different while using ProtocolSet ?

My changes can be seen here: https://github.com/ghoshbishakh/MP-SPDZ/pull/1/files#diff-22da31d62c87d52f22095243f4a749ce4a7f28dd70d6e12cbe96a4db6fab8ff0

ghoshbishakh commented 2 years ago

@mkskeller It seems in order to make ProtocolSetup and ProtocolSet work, I need to make P256Element compatible with Share. Is that correct?

Although P256Element implements ValueInterface it seems it is not enough. ProtocolSetup is looking for P256Element::next which is not there. https://github.com/data61/MP-SPDZ/blob/86a29e28b54b2603daa53723db4420685a86e6a2/Protocols/ProtocolSetup.h#L25-L32

Further, ./Protocols/Share.hpp:22:13 is trying to find P256Element.randomize ./Protocols/fake-stuff.hpp:265:57 needs P256Element.type_short()

I am trying to add these to P256Element to the best of my understanding. @mkskeller Do you think this is the correct approach? Or is there a better way? At the end I need to input some P256Elements as well as open them.

ghoshbishakh commented 2 years ago

If we try to initialize ProtocolSet with Share the issue is that it tries to initialize LivePrep and Protocol as well with Share. This leads to issues like trying to generate Beaver triples of type P256Element which does not make sense: image

https://github.com/data61/MP-SPDZ/blob/86a29e28b54b2603daa53723db4420685a86e6a2/Protocols/ProtocolSet.h#L75-L80

Since we only need input, output I think we have to implement a new subset of ProtocolSet with only usage, output, input. I am trying to do that.

mkskeller commented 2 years ago
  1. a5917de3cf allows initializing ProtocolSetup with the exact prime, which is necessary (not just the length).
  2. Indeed, for shares over P256Element you cannot use ProtocolSet but have to use MAC_Check instead. However, that should be less error-prone than the rest because it doesn't rely on the combination of protocols.
ghoshbishakh commented 2 years ago

@mkskeller Thank you for all your help!