ABY icon indicating copy to clipboard operation
ABY copied to clipboard

B2AGate() returns weird values

Open jpmcruz opened this issue 6 years ago • 25 comments

I am trying a code that performs both Boolean and Arithmetic operations on SIMD values. The first call on the B2AGate() function works fine, but a second call to the same B2AGate generates weird and random-looking numbers. Can the B2AGate function be only called once in a circuit?

I believe my problem is the same as this issue opened last year: https://github.com/encryptogroup/ABY/issues/24

Thank you.

jpmcruz avatar May 18 '18 06:05 jpmcruz

I just experienced the same behavior and it looks like this is due to the boolean sharings being of a bitlen less than the circuit bitlen (e.g. 32). As a workaround for now, try to zero-pad your boolean sharings to full circuit bitlength before conversion.

sebastianst avatar Jun 11 '18 21:06 sebastianst

BTW it really affects the second and following conversions, SIMD or not. The first conversion always succeeds, also if it is of a true simd share.

sebastianst avatar Jun 12 '18 09:06 sebastianst

Thank you for the response. If the first conversion always succeeds (and succeeding conversions fail), is the bitlen still the problem? The error may still occur even if bitlen is the same as the circuit's.

jpmcruz avatar Jun 13 '18 05:06 jpmcruz

I just found out that this workaround only works if all conversions are on the same circuit level. If you have SIMD shares and conversions on different circuit levels, then this workaround doesn't help either... Minimal example is to create a boolean share with nvals=2 and convert it three times in a cycle bool->arith->bool->arith. The second B2A conversion generates random values again. We're investigating the root of the problem...

sebastianst avatar Jun 18 '18 17:06 sebastianst

We have fixed an issue with the B2A conversion in 01ee0dc86e9ceacf2687ebd2a2a2d2213bbbc2c5 There is another related problem that we are aware of and we are working on it at the moment.

dd23 avatar Jun 22 '18 15:06 dd23

Thanks for fixing the B2A conversion issue. What is the related problem?

jpmcruz avatar Jul 03 '18 01:07 jpmcruz

B2A still returns weird random values if it called on the same circuit more than one time. I am not sure if the issue which @dd23 reports above as resolved resolves this problem. B2A clearly isn't working correctly after the first invocation. If you change the example given in #51 by replacing all yao shares to binary shares, you can easily reproduce the problem.

mayank0403 avatar Aug 07 '18 08:08 mayank0403

I recently fixed another bug that affects consecutive conversions on neighbouring layers, see PR #72 . Please try this one out and see if it fixes your problem. Note that you still have to zero-pad any boolean share to full bitlength before the conversion.

sebastianst avatar Aug 07 '18 08:08 sebastianst

Yeah, I was going through your commit only right now. I think you have found the solution. Seems pretty logical to me. Will make the changes and report the results here. Thanks.

mayank0403 avatar Aug 07 '18 08:08 mayank0403

I keep getting SEG Fault when I add the declaration of m_vCONVGates2 in arithsharing.h. Do you have an idea why this is happening? I am working with this commit - d4670e52f515800c3c3bf04190665c8ed1eb0a4a, since the newer ones won't compile.

mayank0403 avatar Aug 07 '18 10:08 mayank0403

I propose you run git cherry-pick b3448f6dcbb371e8fdb88a4c2e2487aa2c4b2397 (hash of this PR's commit) instead of applying the changes manually, or is that what you did? If the current public branch doesn't compile for you, you should file a separate bug report on this.

sebastianst avatar Aug 07 '18 12:08 sebastianst

Doesn't the travis build of the latest public branch commits fail? Doesn't this mean that the project doesn't compile with the latest commits?

mayank0403 avatar Aug 07 '18 12:08 mayank0403

@mayank0403 The build is successful. However, the test cases currently fail on the Travis build server. (I think it has something to do with the race conditions #69.)

lenerd avatar Aug 07 '18 13:08 lenerd

@lenerd Can you address issue #74 ? This is what is the error that I am facing while compiling the project.

mayank0403 avatar Aug 07 '18 13:08 mayank0403

@mayank0403 I have just started a Ubuntu VM and I am looking into it right now.

lenerd avatar Aug 07 '18 13:08 lenerd

@sebastianst I just updated the latest commit with your the commit in your PR (#72 ) and in the code, I am using the same bitlen (32) for creating binary shares as the bitlen for the circuit (32), this code still gives random values with B2A gate being invocated more than one time. millionaire_prob.cpp.tar.gz

mayank0403 avatar Aug 08 '18 09:08 mayank0403

The problem and the outputs resemble to the one raised in #51.

mayank0403 avatar Aug 08 '18 09:08 mayank0403

(Please rather post such code as a gist in the future. Makes in easier to comment and update.) In line 63

condition = acirc->PutB2AGate(bcirc->PutGTGate(variable, put_cons32_gate(bcirc, 0)));

You don't zero-pad the GTGate share before conversion. Like I wrote earlier, zero-padding still needs to be done before conversion, i.e., add constant zero gates to the wires until full bitlen (32 in your example).

This manual intervention is admittedly quite inconvenient and maybe it makes sense to do this implicitly in PutB2AGate. @dd23 do you agree? We can add it until B2A is fully fixed to also handle non-full-bitlength conversions properly.

sebastianst avatar Aug 08 '18 09:08 sebastianst

@sebastianst would it be possible for you to share the code where you zero-pad the binary shares before conversion? I cannot find a very lucid example or a description of how something like this could be done in the developer's manual. I was trying to do something like this -

std::vector<uint32_t> tmp = variable->get_wires();
tmp.insert(tmp.begin(), tmp.end(), tmp.end()+31);
variable = create_new_share(tmp, bcirc);

(Here variable holds the binary shares which will be passed to the B2A gate for conversion.) But clearly this doesn't work. How do I explicitly put zeros into the wires even if I allocate new wires?

mayank0403 avatar Aug 09 '18 11:08 mayank0403

Never mind. I found the way.

std::vector<uint32_t> tmp = variable->get_wires();
share* zerobinary = put_cons32_gate(bcirc, 0);
std::vector<uint32_t> zerowires = zerobinary->get_wires();
zerobinary->set_wire_id(0, tmp[0]);
variable = zerobinary;

This works.

mayank0403 avatar Aug 09 '18 12:08 mayank0403

Yep that's a way. btw you can skip the 3rd line where you set zerowires since you don't use it.

So does the conversion now work for you? If yes, we can close the issue.

sebastianst avatar Aug 09 '18 15:08 sebastianst

Yeah, it works. Thanks.

mayank0403 avatar Aug 09 '18 15:08 mayank0403

I'd rather keep this issue open until the padding problem has been sorted out properly. The manual zero-padding adds some overhead and works as a workaround, but maybe we can implement a proper and more efficient solution.

In any case: thanks for your input so far!

dd23 avatar Aug 09 '18 16:08 dd23

PR #72 now has the full fix. @mayank0403 and others, you can give it a try and tell us if this also works without zero padding for you. Note that there's a bug in ENCRYPTO_utils/CBitVector::SetBitsPosOffset and until it is fixed, you also need to apply 07646aed48fc9067670517777caba05c264caaaf for the conversion to work.

sebastianst avatar Aug 13 '18 19:08 sebastianst

@sebastianst CBitVector::SetBitsPosOffset is now fixed and the submodules are updated accordingly.

lenerd avatar Aug 19 '18 22:08 lenerd