makeShare
In two-party operations, this function is called to split the original data of node 0 (compute party) and node 1 (non-compute party) into shares. When node 0 calls this function, it sets isRecvShare to 1 to receive the shares sent by node 1, and then sets isRecvShare to 0 to split its own data into shares. When the non-compute party calls this function, it sets isRecvShare to 0 to split its own data into shares and then sends the shares to the compute party. In three-party operations, this function is called to split the original data of any two nodes among node 0 (compute party) and nodes 1 and 2 (non-compute parties) into shares. Assume that nodes 0 and 1 have data. When node 0 calls this function, it sets isRecvShare to 1 to receive the shares sent by node 1, and then sets isRecvShare to 0 to split its own data into shares. When node 1 calls this function, it sets isRecvShare to 0 to split its own data into shares and sends the shares to node 0, and sets isRecvShare to 1 to receive the shares sent by node 0. Then, node 2 sets isRecvShare to 1 to receive the shares sent by node 0 and sets isRecvShare to 1 to receive the shares sent by node 1.
int makeShare(
DG_TeeCtx *dgTeeCtx,
int isRecvShare,
DG_TeeInput *input,
DG_MpcShare **share
)
Parameters
Parameter |
Description |
Value Range |
Input/Output |
|---|---|---|---|
dgTeeCtx |
KCAL context |
Context initialized in section initTeeCtx. |
Input |
isRecvShare |
|
0 or 1. |
Input |
input |
This is the original data. If isRecvShare is set to 0, input can be null. If isRecvShare is not set to 0, input cannot be null. |
Currently, only the double type is supported. |
Input |
share |
The type of the share result: DG_MpcShare |
It is null as a single pointer and cannot be null as a double pointer. |
Output |
Member |
Type |
Description |
|---|---|---|
data |
DG_MpcDataUnion |
The types of the input data strings, doubleNumbers, and u64Numbers are respectively DG_String *, double *, and u64 *. |
size |
uint64_t |
Data volume |
dataType |
DG_MpcDataType |
The enumerated data type is as follows: MPC_INT (cryptographic comparison) MPC_DOUBLE (cryptographic addition, subtraction, maximum, minimum, multiplication, division, averaging, summation, and sorting) |
Member |
Type |
Description |
|---|---|---|
strings |
DG_String |
String array |
u64Numbers |
u64 |
u64 array |
doubleNumbers |
double |
Double array |
Member |
Type |
Description |
|---|---|---|
dataShare |
Share |
Share structure |
size |
unsigned long |
Data volume |
shareType |
DG_ShareType |
Share type |
Member |
Description |
|---|---|
FIX_POINT |
Data is converted into the double type when revealShare is executed. |
NON_FIX_POINT |
Data is converted into the u64 type when revealShare is executed. |
Member |
Type |
Description |
|---|---|---|
shares |
u64* |
Multiple shares corresponding to one piece of plaintext data |
size |
u64 |
The number of shares |
Return Values
- Success: 0 is returned.
- Failure: The error code is returned.
Error Codes
Error Code |
Value |
Description |
Remarks |
|---|---|---|---|
DG_FAILURE |
4501 |
Data share splitting failure |
Failed to verify the parameters. Failed to split data into shares. Failed to receive data from the other node. |
Dependency
- dgTeeCtx depends on the successful initialization of initTeeCtx.
- You need to call the negotiateSeeds API to distribute seeds to all nodes.
- #include "data_guard_mpc.h": required header file
Example
#include "data_guard_mpc.h"
std::unique_ptr<double[]> inData = std::make_unique<double[]>(datas.size());
for (int i = 0; i < datas.size(); i++) {
inData[i] = (std::stod(datas[i].c_str())) * 1.0;
}
// DG_TeeInput teeInput indicates the data shares from the compute party.
teeInput.data.doubleNumbers = inData.get();
teeInput.size = static_cast<int>(datas.size());
teeInput.dataType = MPC_DOUBLE;
int res = aritOpts.negotiateSeeds(dgTee);
printf("exchange seed res = %d\n", res);
DG_MpcShareSet shareDat;
std::unique_ptr<DG_MpcShare[]> share = std::make_unique<DG_MpcShare[]>(2);
DG_MpcShare *share1 = nullptr;
DG_MpcShare *share2 = nullptr;
DG_TeeOutput *output = nullptr;
if (nodeId == 0) { // Compute node 0 receives the data shares of compute node 1 and then splits the data of compute node 0 itself into shares.
res = aritOpts.makeShare(dgTee, 1, nullptr, &share1); // teeInput
if (res != 0) {
printf("node 0 recv share data.[ret=%d]\n", res);
return res;
}
res = aritOpts.makeShare(dgTee, 0, teeInput, &share2);
if (res != 0) {
printf("node 0 make share self shar data fail.[ret=%d]\n", res);
return res;
}
} else { // Correspondingly, compute node 1 splits the data of compute node 1 itself into shares and then receives the data shares of compute node 0.
res = aritOpts.makeShare(dgTee, 0, teeInput, &share1);
if (res != 0) {
printf("node 1 make share self shar data fail.[ret=%d]\n", res);
return res;
}
res = aritOpts.makeShare(dgTee, 1, nullptr, &share2);
if (res != 0) {
printf("make share self shar data.[ret=%d]\n", res);
return res;
}
}
Test result: res is 0, and shares 1 and 2 are not null.
// Data shares
Note: The example is for reference only. It describes how to read data from a file for testing and cannot be executed.
Test result: res is 0 and the shares are not null.
- Call the makeShare API using the aritOpts output of the successful DG_InitArithmeticOpts call.
- If either node (compute node 0 or 1) returns an error code when calling an API, the node needs to use a task scheduling mechanism to notify the other node to terminate the service process. For example, if compute node 1 returns an error code when calling the makeShare API and compute node 0 is waiting to receive shares, compute node 1 needs to notify compute node 0 to stop receiving.