snwagh / securenn-public

Implementation of protocols in SecureNN.
124 stars 30 forks source link

How to reconstruct the result of matrix multiplication? #5

Closed zzz130981 closed 4 years ago

zzz130981 commented 4 years ago

Hello, I'm doing some arithmetical operation, and I rewrote src/main.cpp,. The simplified core code is as follow:

size_t size = 1;
vector<myType> data1(size), data2(size), ans(size);
generateData(data1);    //generate size random numbers between [0,10] and assign them to data1
generateData(data2);    //generate size random numbers between [0,10] and assign them to data2
funcMatMulMPC(data1, data2, ans, 1, 1, 1, 0, 0);

cout << "data is as above:" << endl;
cout << data1[0] << " " << data2[0] <<  endl;
funcReconstruct2PC(ans, size, "ans is");

Then I run "make abcTerminal", however, I cannot reconstruct it and only get:

data is as above:
2 4 0
ERROR reading from socket
Size = 8, Left = 8, n = -1
Receive myType vector error
ans is: 0 
Execution completed

Screenshot as follows: 2020-02-11 23-31-54 的屏幕截图

I guess the reason is that the terminal only print P0's result, so I need to print results of P1&P2, isn't it? If I am right, I don't know how to do it.

snwagh commented 4 years ago

The devil is usually in the details (make sure you provide a MWE, which would include the code for generateData()) The errors are usually where you least expect them.

  1. The communication error makes me suspect which parties are calling the codes. You might have to call funcReconstruct2PC(ans, size, "ans is") within if (partyNum == PARTY_A or partyNum == PARTY_B) (take a look at the implementation of funcReconstruct2PC)
  2. Secondly, the funcMatMulMPC implicitly does the truncation. If you expect to have a result 2x4 = 8, you will have to set the FLOAT_PRECISION to 0 (here). Right now, if the precision is high, the answer will be 2x4/2^f where f is the precision and hence you get a 0. Another point to note here is that the mat-mul will operate on underlying secret, so if both parties generate random values in [0,10], then the actual multiplication will be over the sum of the random numbers.
  3. Finally, to get the output of the other files, you can run the 3 parties on 3 separate terminals and that way you'll have access to the 3 outputs. Also, it might help you to take a quick look at any simple makefile tutorial. You effectively need to run lines 87-89 here without the output piping in the end (>/dev/null).
zzz130981 commented 4 years ago

Yes, you are right! I forgot to process agrv, so no matter what I input, the system is always standalone instead of three servers. So I fix it.

Now, I want to do a simple matrix multiplication(such as [2.0]*[5.0]=[10.0]) to verify my right use of FuncMatMulMPC(). However, although I have processed agrv rightly, I still failed.

The MWE is as follow. Because I don't know how to share a number (such as 2.0) between P0&P1, I split it to two shares by hand and assign them to servers, respectively(2.0 = 1.0 + 1.0, 5.0 = 1.0+4.0). But I still wonder whether you have provided some interfaces to share a number.

int main(int argc, char** argv)
{
     parseInputs(argc, argv);
/****************************** AES SETUP and SYNC ******************************/ 
    aes_indep = new AESObject(argv[4]);
    aes_common = new AESObject(argv[5]);
    aes_a_1 = new AESObject("files/keyD");
    aes_a_2 = new AESObject("files/keyD");
    aes_b_1 = new AESObject("files/keyD");
    aes_b_2 = new AESObject("files/keyD");
    aes_c_1 = new AESObject("files/keyD");
    aes_parallel = new ParallelAESObject(argv[5]);

    if (!STANDALONE)
    {
        initializeCommunication(argv[3], partyNum);
        synchronize(2000000);   
    }

    if (PARALLEL)
        aes_parallel->precompute();
/****************************** zzz.work*****************************/ 
       vector<myType> data0(size), data1(size), ans(size);
    if(partyNum == PARTY_A) {
        data0[0]=floatToMyType(1.0);
        data1[0]=floatToMyType(1.0);
    }
    if(partyNum == PARTY_B) {
        data0[0]=floatToMyType(1.0);
        data1[0]=floatToMyType(4.0);
    }
    printf("party%d data0:%d data1:%d\n", partyNum, data0[0], data1[0]);
    funcMatMulMPC(data0, data1, ans, 1, 1, 1, 0, 0);
    printf("party%d data0:%d data1:%d ans:%d\n", partyNum, data0[0], data1[0],ans[0]);

    if(PRIMARY) {
        funcReconstruct2PC(ans, 1, "ans is");
    }

/****************************** CLEAN-UP ******************************/ 
    delete aes_common;
    delete aes_indep;
    delete aes_a_1;
    delete aes_a_2;
    delete aes_b_1;
    delete aes_b_2;
    delete aes_c_1;
    delete aes_parallel;
    if (partyNum != PARTY_S)
        deleteObjects();

    return 0;
}

In order to output the output of P0&P1, I deleted the ">/dev/null" of 87st and 88st line in makefile. Lastly, the above program output:

2020-02-12 18-13-21 的屏幕截图

I have modified the FLOAT_PRECISION to be 0 instead of 13, however, it doesn't work:

2020-02-12 18-43-00 的屏幕截图

(Can you see my picture? Why I cannot see it?) party1 data0:1 data1:4 party0 data0:1 data1:1 party2 data0:0 data1:0 party2 data0:0 data1:0 ans:0 party1 data0:1 data1:4 ans:1815181012 party0 data0:1 data1:1 ans:1037503814 ans is: -647131593038068710 Execution completed

I have read the source code of Functionalities.cpp & FCLayer.cpp to learn more about funcMatMulMPC(), however, I still cannot fix the bug.

snwagh commented 4 years ago

Please check with the sample code and see if you can spot the bug in your code.

  1. https://github.com/snwagh/securenn-public/blob/master/src/Functionalities.cpp#L1815
  2. https://github.com/snwagh/securenn-public/blob/master/src/Functionalities.cpp#L1928

Also make sure you print the right values, %d might be system specific and print 32 bit outputs as opposed to 64. Use the print functions in tools.cpp

zzz130981 commented 4 years ago

Unbelievable! debugMatmul() doesn't work in my PC, either. I only modified src/main.cpp as follow:

int main(int argc, char** argv)
{
     parseInputs(argc, argv);
/****************************** AES SETUP and SYNC ******************************/ 
    aes_indep = new AESObject(argv[4]);
    aes_common = new AESObject(argv[5]);
    aes_a_1 = new AESObject("files/keyD");
    aes_a_2 = new AESObject("files/keyD");
    aes_b_1 = new AESObject("files/keyD");
    aes_b_2 = new AESObject("files/keyD");
    aes_c_1 = new AESObject("files/keyD");
    aes_parallel = new ParallelAESObject(argv[5]);

    if (!STANDALONE)
    {
        initializeCommunication(argv[3], partyNum);
        synchronize(2000000);   
    }

    if (PARALLEL)
        aes_parallel->precompute();
/****************************** zzz.work*****************************/ 
    debugMatMul();

/****************************** CLEAN-UP ******************************/ 
    delete aes_common;
    delete aes_indep;
    delete aes_a_1;
    delete aes_a_2;
    delete aes_b_1;
    delete aes_b_2;
    delete aes_c_1;
    delete aes_parallel;
    if (partyNum != PARTY_S)
        deleteObjects();

    return 0;
}

And run "make abcTerminal", however, I only get: 2020-02-13 10-42-40 的屏幕截图 It means that funcReconstruct2PC() functions well, however, why funcMatmulMPC() doesn't work?

zzz130981 commented 4 years ago

Hello, I fix it! Please check whether there is files/KeyD!