encryptogroup / MOTION

An efficient, user-friendly, modular, and extensible framework for mixed-protocol secure multi-party computation with two or more parties
MIT License
85 stars 40 forks source link

Help: `BitVector` error on simple example. #20

Closed Isweet closed 2 years ago

Isweet commented 2 years ago

I've written a very simple example and I'm getting errors. The program below, when run on my machine, gives back: libc++abi: terminating with uncaught exception of type std::out_of_range: BitVector: accessing 0 of 0.

If I change the variable c from the xor (^) of a and b to the and (&) of a and b, then the programs enter deadlock. I am running as $ ./test 0 & ./test 1 where test is the name of the executable.

My guess is that it is user error on my part. Could you help me understand how I am misusing the library?

#include "base/party.h"
#include "protocols/share_wrapper.h"
#include "utility/bit_vector.h"
#include "communication/communication_layer.h"
#include "communication/tcp_transport.h"

using namespace encrypto::motion;

Party MakeParty(size_t my_id, const char **hosts, ushort *ports, size_t len) {
  communication::TcpPartiesConfiguration parties_configuration(len);

  for (size_t party_id = 0; party_id < len; party_id++) {
    std::string host(hosts[party_id]);
    ushort port = ports[party_id];
    parties_configuration.at(party_id) = std::make_pair(std::string(hosts[party_id]), ports[party_id]);
  }

  communication::TcpSetupHelper helper(my_id, parties_configuration);
  auto communication_layer = std::make_unique<communication::CommunicationLayer>(my_id, helper.SetupConnections());
  return Party(std::move(communication_layer));
}

ShareWrapper MakeBoolShare(Party& party, bool share) {
  BitVector share_bv(share);
  std::span input(&share_bv, 1);
  return ShareWrapper(party.SharedIn<MpcProtocol::kBooleanGmw>(input));
}

int main(int argc, char *argv[]) {
  size_t my_id = atoi(argv[1]);
  const char *hosts[2] = { "127.0.0.1", "127.0.0.1" };
  ushort ports[2] = { 23000, 23001 };
  Party party = MakeParty(my_id, hosts, ports, 2);
  ShareWrapper a = MakeBoolShare(party, my_id == 0 ? false : true);
  ShareWrapper b = MakeBoolShare(party, my_id == 0 ? false : true);
  ShareWrapper c(a ^ b);

  party.Run();
  party.Finish();

  std::cout << my_id << ": " << c.As<bool>() << std::endl;

  return 0;
}
Isweet commented 2 years ago

Okay, after some experimenting it seems like I'm constructing the std::span<BitVector<>> incorrectly when constructing the shares. Not sure how yet though.

Isweet commented 2 years ago

Looks like doing BitVector share_bv(1, share); rather than BitVector share_bv(share); has fixed it for me. Perhaps the BitVector(bool) constructor is broken / only meant for internal use?

Oleksandr-Tkachenko commented 2 years ago

The thing is, there is no BitVector(bool value) constructor. I think that bool gets promoted to a size_t and this constructor gets called as BitVector(static_cast(value), false), so 0 bits in case of value == false (default-initialized as false). Yes, that's quite hard to spot, but I, spontaneously, don't see a good solution. Any suggestions are very welcome.

IIRC, the problem was that by adding an explicit BitVector(bool) constructor, calls to BitVector(std::size_t, bool value = false) don't get implicitly converted from other types, e.g., BitVector(10) would not compile, so you would always need to write BitVector(std::size_t(10)). Thus, I decided to stick to an API more similar to std::vector.

Isweet commented 2 years ago

Thanks for clarifying!

It might be nice for others to have some documentation of how to use the BitVector constructor(s) more readily available. I figured it out by looking at the definition of ToInput, specifically this line: https://github.com/encryptogroup/MOTION/blob/master/src/motioncore/utility/bit_vector.cpp#L1099.

Perhaps there's a use of the BitVector(size_t, bool) constructor elsewhere which you can use as documentation for newcomers? I looked in https://github.com/encryptogroup/MOTION/blob/master/src/test/test_bgmw.cpp briefly but nothing stuck out. Understandably, all the inputs being constructed are > 1 bit.