Help: `BitVector` error on simple example.
Isweet opened this issue · 4 comments
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;
}
Okay, after some experimenting it seems like I'm constructing the std::span<BitVector<>>
incorrectly when constructing the shares. Not sure how yet though.
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?
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_caststd::size_t(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
.
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.