Multiparty decryption error

I found that when I split the three party threshold multi key homomorphic sample code into three files for collaborative calculation, multiplication decryption would cause errors due to large approximation errors. I output some of the intermediate parameters and found that the logstd was too high, and the Elementwas also significantly different from normal decryption. I’m not sure if there was a problem with my code flow. Could you please help me check it.
This is the output of the error and intermediate variable


All other code logic is consistent with the sample code.
Thanks a lot.

After node A generates a cryptocontext, it will first be sent to nodes B and C

This is the multiplication calculation key generation code for node A

This is the multiplication calculation key generation code for node B

This is the multiplication calculation key generation code for node C

Could you upload a representative example (the source code file) that recreates this issue? It is hard to debug using screen shots of a distributed application. You could just create one file (without serialization) to make sure the threshold FHE logic is implemented correctly. If you still have an issue in that single-file setup, please upload here and we will take a look at it.

This is the code for node A

#include "openfhe.h"
#include <iostream>
#include <algorithm>
#include <vector>
#include <chrono>
#include <fstream>
#include <string>
#include <cstring>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <functional>
#include <map>
#include <memory>
#include <utility>
//#include "pybind11/pybind11.h"
//#include "pybind11/stl.h"
//namespace py = pybind11;

// header files needed for serialization
#include "ciphertext-ser.h"
#include "cryptocontext-ser.h"
#include "key/key-ser.h"
#include "scheme/ckksrns/ckksrns-ser.h"

#define BUFFER_SIZE 4096

using namespace std;
using namespace lbcrypto;

const std::string DATAFOLDER = "demoData1";

int receive(int listeningPort, std::string saveFilename){
//    int listeningPort = 12345;
//    std::string saveFilename = "cryptocontext.txt";

    // 创建监听套接字
    int listeningSocketFD = socket(AF_INET, SOCK_STREAM, 0);
    if (listeningSocketFD == -1) {
        std::cerr << "无法创建监听套接字" << std::endl;
        return 1;
    }

    // 设置本地地址信息
    sockaddr_in localAddress{};
    localAddress.sin_family = AF_INET;
    localAddress.sin_addr.s_addr = INADDR_ANY;
    localAddress.sin_port = htons(listeningPort);

    // 绑定监听套接字到本地地址
    if (bind(listeningSocketFD, (struct sockaddr*)&localAddress, sizeof(localAddress)) < 0) {
        std::cerr << "绑定套接字失败" << std::endl;
        return 1;
    }

    // 开始监听
    if (listen(listeningSocketFD, 1) < 0) {
        std::cerr << "开始监听失败" << std::endl;
        return 1;
    }

    std::cout << "等待连接..." << std::endl;

    // 接受连接请求
    sockaddr_in clientAddress{};
    socklen_t clientAddressLength = sizeof(clientAddress);
    int connectionSocketFD = accept(listeningSocketFD, (struct sockaddr*)&clientAddress, &clientAddressLength);
    if (connectionSocketFD < 0) {
        std::cerr << "接受连接失败" << std::endl;
        return 1;
    }

    std::cout << "已连接" << std::endl;

    // 创建文件来保存接收的数据
    std::ofstream outputFile(saveFilename);
    if (!outputFile) {
        std::cerr << "无法创建文件:" << saveFilename << std::endl;
        return 1;
    }

    // 接收数据并写入文件

    char buffer[BUFFER_SIZE];
    ssize_t bytesRead;
    while ((bytesRead = recv(connectionSocketFD, buffer, BUFFER_SIZE, 0)) > 0) {
        // 写入文件
        outputFile.write(buffer, bytesRead);
    }

//    char buffer[BUFFER_SIZE];
//    int bytesRead;
//    while ((bytesRead = recv(connectionSocketFD, buffer, BUFFER_SIZE, 0)) > 0) {
//        // 写入文件
//        outputFile.write(buffer, bytesRead);
//    }

    // 关闭套接字和文件
    close(connectionSocketFD);
    close(listeningSocketFD);
    outputFile.close();

    std::cout << "文件接收完成" << std::endl;

    return 0;
}

int send(int serverPort, std::string serverIP, std::string filename){
//    std::string serverIP = "192.168.1.103";
//    int serverPort = 12345;
//    std::string filename = "demoData/cryptocontext.txt";

    // 打开文件
    std::ifstream file(filename);
    if (!file) {
        std::cerr << "无法打开文件:" << filename << std::endl;
        return 1;
    }

    // 创建套接字
    int socketFD = socket(AF_INET, SOCK_STREAM, 0);
    if (socketFD == -1) {
        std::cerr << "无法创建套接字" << std::endl;
        return 1;
    }

    // 设置目标服务器的地址信息
    sockaddr_in serverAddress{};
    serverAddress.sin_family = AF_INET;
    serverAddress.sin_port = htons(serverPort);
    if (inet_pton(AF_INET, serverIP.c_str(), &(serverAddress.sin_addr)) <= 0) {
        std::cerr << "无效的IP地址:" << serverIP << std::endl;
        return 1;
    }

    // 连接到目标服务器

    int i = 0;
    for ( ; i < 50; ++i) {
        if (connect(socketFD, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) < 0) {
            std::cerr << "尝试连接失败,继续等待" << std::endl;
            sleep(1);
        }
        else break;
    }
    if (i == 5)
        return 1;

//    if (connect(socketFD, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) < 0) {
//        std::cerr << "连接失败" << std::endl;
//        return 1;
//    }

//    if (!connectWithTimeout(socketFD, (struct sockaddr*)&serverAddress, sizeof(serverAddress), 5)) {
//        std::cerr << "连接到目标主机失败" << std::endl;
//        return 1;
//    }

    // 逐行读取文件并发送数据

    char buffer[BUFFER_SIZE];
    while (!file.eof()) {
        file.read(buffer, BUFFER_SIZE);
        ssize_t bytesRead = file.gcount();

        // 发送数据
        ssize_t bytesSent = send(socketFD, buffer, bytesRead, 0);
        if (bytesSent == -1) {
            std::cerr << "发送数据失败" << std::endl;
            break;
        }
    }

//    std::string line;
//    while (std::getline(file, line)) {
//        // 发送数据
//        if (send(socketFD, line.c_str(), line.length(), 0) == -1) {
//            std::cerr << "发送数据失败" << std::endl;
//            return 1;
//        }
//    }

    // 关闭套接字和文件
    close(socketFD);
    file.close();

    std::cout << "文件发送完成" << std::endl;

    return 0;
}

int main() {
//    auto start = std::chrono::high_resolution_clock::now();
    usint batchSize = 16;

    CCParams <CryptoContextCKKSRNS> parameters;
    parameters.SetMultiplicativeDepth(3);
    parameters.SetScalingModSize(50);
    parameters.SetBatchSize(batchSize);

    CryptoContext <DCRTPoly> cc = GenCryptoContext(parameters);
    // enable features that you wish to use
    cc->Enable(PKE);
    cc->Enable(KEYSWITCH);
    cc->Enable(LEVELEDSHE);
    cc->Enable(ADVANCEDSHE);
    cc->Enable(MULTIPARTY);

    std::cout << "\nThe cryptocontext has been generated." << std::endl;

    // Serialize cryptocontext
    if (!Serial::SerializeToFile(DATAFOLDER + "/cryptocontext.txt", cc, SerType::BINARY)) {
        std::cerr << "Error writing serialization of the crypto context to "
                     "cryptocontext.txt"
                  << std::endl;
        return 1;
    }
    std::cout << "The cryptocontext has been serialized." << std::endl;

    send(10305, "192.168.1.105", DATAFOLDER + "/cryptocontext.txt");
    send(10306, "192.168.1.106", DATAFOLDER + "/cryptocontext.txt");
    ////////////////////////////////////////////////////////////
    // Set-up of parameters
    ////////////////////////////////////////////////////////////

    // Output the generated parameters
    std::cout << "p = " << cc->GetCryptoParameters()->GetPlaintextModulus() << std::endl;
    std::cout << "n = " << cc->GetCryptoParameters()->GetElementParams()->GetCyclotomicOrder() / 2 << std::endl;
    std::cout << "log2 q = " << log2(cc->GetCryptoParameters()->GetElementParams()->GetModulus().ConvertToDouble())
              << std::endl;

    // Initialize Public Key Containers for two parties A and B
    KeyPair <DCRTPoly> kp_1;

//    KeyPair<DCRTPoly> kpMultiparty;

    ////////////////////////////////////////////////////////////
    // Perform Key Generation Operation
    ////////////////////////////////////////////////////////////

    std::cout << "Running key generation (used for source data)..." << std::endl;

    // Round 1 (party A)

    std::cout << "Round 1 (party A) started." << std::endl;
//    auto start_keygen = std::chrono::high_resolution_clock::now();
//    auto start_keygen1 = std::chrono::high_resolution_clock::now();

    kp_1 = cc->KeyGen();

    // Serialize the public key
    if (!Serial::SerializeToFile(DATAFOLDER + "/publickey1.txt", kp_1.publicKey, SerType::BINARY)) {
        std::cerr << "Error writing serialization of publickey1 to publickey1.txt" << std::endl;
        return 1;
    }
    std::cout << "The publickey1 has been serialized." << std::endl;

    send(103052, "192.168.1.105", DATAFOLDER + "/publickey1.txt");

//    auto start_multkeygen = std::chrono::high_resolution_clock::now();
    // Generate evalmult key part for A
    auto evalMultKey = cc->KeySwitchGen(kp_1.secretKey, kp_1.secretKey);

    if (!Serial::SerializeToFile(DATAFOLDER + "/evalMultKey.txt", evalMultKey, SerType::BINARY)) {
        std::cerr << "Error writing serialization of evalMultKey to evalMultKey.txt" << std::endl;
        return 1;
    }
    std::cout << "The evalMultKey has been serialized." << std::endl;

    send(10305, "192.168.1.105", DATAFOLDER + "/evalMultKey.txt");
    send(10306, "192.168.1.106", DATAFOLDER + "/evalMultKey.txt");

    receive(10603, DATAFOLDER + "/evalMultABC.txt");

    EvalKey <DCRTPoly> evalMultABC;
    if (Serial::DeserializeFromFile(DATAFOLDER + "/evalMultABC.txt", evalMultABC, SerType::BINARY) == false) {
        std::cerr << "Could not read evalMultABC" << std::endl;
        return 1;
    }
    std::cout << "The evalMultABC has been deserialized." << std::endl;

    receive(10603, DATAFOLDER + "/publickey3.txt");

    PublicKey <DCRTPoly> pk3;
    if (Serial::DeserializeFromFile(DATAFOLDER + "/publickey3.txt", pk3, SerType::BINARY) == false) {
        std::cerr << "Could not read publickey3" << std::endl;
        return 1;
    }
    std::cout << "The public key3 has been deserialized." << std::endl;

    auto evalMultAABC = cc->MultiMultEvalKey(kp_1.secretKey, evalMultABC, pk3->GetKeyTag());

    if (!Serial::SerializeToFile(DATAFOLDER + "/evalMultAABC.txt", evalMultAABC, SerType::BINARY)) {
        std::cerr << "Error writing serialization of evalMultAABC to evalMultAABC.txt" << std::endl;
        return 1;
    }
    std::cout << "The evalMultAABC has been serialized." << std::endl;

    send(10306, "192.168.1.106", DATAFOLDER + "/evalMultAABC.txt");

    receive(10603, DATAFOLDER + "/evalMultFinal.txt");

    cc->ClearEvalMultKeys();

    std::ifstream emkeys2(DATAFOLDER + "/evalMultFinal.txt", std::ios::in | std::ios::binary);
    if (!emkeys2.is_open()) {
        std::cerr << "I cannot read serialization from " << DATAFOLDER + "/evalMultFinal.txt" << std::endl;
        return 1;
    }
    if (cc->DeserializeEvalMultKey(emkeys2, SerType::BINARY) == false) {
        std::cerr << "Could not deserialize the evalMultFinal file" << std::endl;
        return 1;
    }
    std::cout << "Deserialized the evalMultFinal." << std::endl;

    const auto evalMultFinal_p = cc->GetAllEvalMultKeys().begin();

    auto evalMultFinal = (*evalMultFinal_p).second[0];

    cc->InsertEvalMultKey({evalMultFinal});

//    auto end_multkeygen = std::chrono::high_resolution_clock::now();
    //---------------------------------------------------
    std::cout << "Running evalsum key generation (used for source data)..." << std::endl;
//    auto start_sumkeygen = std::chrono::high_resolution_clock::now();
    // Generate evalsum key part for A

    cc->EvalSumKeyGen(kp_1.secretKey);

    auto evalSumKeys = std::make_shared < std::map < usint, EvalKey<DCRTPoly>>>(cc->GetEvalSumKeyMap(
            kp_1.secretKey->GetKeyTag()));

    // Serialize the public key
    if (!Serial::SerializeToFile(DATAFOLDER + "/evalSumKeys.txt", evalSumKeys, SerType::BINARY)) {
        std::cerr << "Error writing serialization of public key to evalSumKeys.txt" << std::endl;
        return 1;
    }
    std::cout << "The evalSumKeys has been serialized." << std::endl;

//    cc->InsertEvalSumKey(evalSumKeys);


    send(10305, "192.168.1.105", DATAFOLDER + "/evalSumKeys.txt");
    send(10306, "192.168.1.106", DATAFOLDER + "/evalSumKeys.txt");
    std::cout << "The eval sum keys have been generated." << std::endl;

    // Serialize the relinearization (evaluation) key for homomorphic
    // multiplication

//    auto end_sumkeygen = std::chrono::high_resolution_clock::now();
    ////////////////////////////////////////////////////////////
    // Encode source data
    ////////////////////////////////////////////////////////////
    std::vector<double> vectorOfInts1 = {1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1, 0};

//    std::vector<double> input = {2.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8, 9, 10, 0, 0};
//    auto start_encode = std::chrono::high_resolution_clock::now();

    Plaintext plaintext1 = cc->MakeCKKSPackedPlaintext(vectorOfInts1);

//    auto end_encode = std::chrono::high_resolution_clock::now();

    ////////////////////////////////////////////////////////////
    // Encryption
    ////////////////////////////////////////////////////////////
//    auto start_encrypt = std::chrono::high_resolution_clock::now();

    Ciphertext <DCRTPoly> ciphertext1;
//    Ciphertext<DCRTPoly> ciphertext4;//new

    ciphertext1 = cc->Encrypt(pk3, plaintext1);
//	ciphertext4 = cc->Encrypt(kp3.publicKey, plaintext4);//new

    if (!Serial::SerializeToFile(DATAFOLDER + "/" + "ciphertext1.txt", ciphertext1, SerType::BINARY)) {
        std::cerr << "Error writing serialization of ciphertext 1 to ciphertext1.txt" << std::endl;
        return 1;
    }
    std::cout << "The first ciphertext has been serialized." << std::endl;

    send(103063, "192.168.1.106", DATAFOLDER + "/" + "ciphertext1.txt");

//    auto end_encrypt = std::chrono::high_resolution_clock::now();

    ////////////////////////////////////////////////////////////
    // EvalAdd Operation on Re-Encrypted Data
    ////////////////////////////////////////////////////////////

    ////////////////////////////////////////////////////////////
    // Decryption after Accumulation Operation on Encrypted Data with Multiparty
    ////////////////////////////////////////////////////////////

    Plaintext plaintextAddNew1;

    DCRTPoly partialPlaintext1;

    Plaintext plaintextMultipartyNew;

    // distributed decryption

    receive(10603, DATAFOLDER + "/" + "ciphertextAdd123.txt");

    Ciphertext <DCRTPoly> ciphertextAdd123;
    if (Serial::DeserializeFromFile(DATAFOLDER + "/ciphertextAdd123.txt", ciphertextAdd123, SerType::BINARY) == false) {
        std::cerr << "Could not read the ciphertextAdd123" << std::endl;
        return 1;
    }
    std::cout << "The ciphertextAdd123  has been deserialized." << std::endl;

    auto sumciphertextPartial1_v = cc->MultipartyDecryptLead({ciphertextAdd123}, kp_1.secretKey);

    Ciphertext <DCRTPoly> sumciphertextPartial1 = sumciphertextPartial1_v[0];

    if (!Serial::SerializeToFile(DATAFOLDER + "/" + "sumciphertextPartial1.txt", sumciphertextPartial1,
                                 SerType::BINARY)) {
        std::cerr << "Error writing serialization of sumciphertextPartial1 to sumciphertextPartial1.txt" << std::endl;
        return 1;
    }
    std::cout << "The sumciphertextPartial1 has been serialized." << std::endl;

    send(10306, "192.168.1.106", DATAFOLDER + "/" + "sumciphertextPartial1.txt");

//    auto start_multdecrypt = std::chrono::high_resolution_clock::now();

    receive(10603, DATAFOLDER + "/" + "ciphertextMult.txt");

    Ciphertext <DCRTPoly> ciphertextMult;
    if (Serial::DeserializeFromFile(DATAFOLDER + "/ciphertextMult.txt", ciphertextMult, SerType::BINARY) == false) {
        std::cerr << "Could not read the ciphertextMult" << std::endl;
        return 1;
    }
    std::cout << "The ciphertextMult has been deserialized." << std::endl;

    auto multciphertextPartial1_v = cc->MultipartyDecryptLead({ciphertextMult}, kp_1.secretKey);

    Ciphertext <DCRTPoly> multciphertextPartial1 = multciphertextPartial1_v[0];

    if (!Serial::SerializeToFile(DATAFOLDER + "/" + "multciphertextPartial1.txt", multciphertextPartial1,
                                 SerType::BINARY)) {
        std::cerr << "Error writing serialization of multciphertextPartial1 to multciphertextPartial1.txt" << std::endl;
        return 1;
    }
    std::cout << "The multciphertextPartial1 has been serialized." << std::endl;

    send(10306, "192.168.1.106", DATAFOLDER + "/" + "multciphertextPartial1.txt");

}

This is the code for node B

#include "openfhe.h"
#include <iostream>
#include <algorithm>
#include <vector>
#include <chrono>
#include <fstream>
#include <string>
#include <cstring>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <functional>
#include <map>
#include <memory>
#include <utility>
//#include "pybind11/pybind11.h"
//#include "pybind11/stl.h"
//namespace py = pybind11;

// header files needed for serialization
#include "ciphertext-ser.h"
#include "cryptocontext-ser.h"
#include "key/key-ser.h"
#include "scheme/ckksrns/ckksrns-ser.h"

#define BUFFER_SIZE 4096

using namespace std;
using namespace lbcrypto;

const std::string DATAFOLDER = "demoData2";

int receive(int listeningPort, std::string saveFilename){
//    int listeningPort = 12345;
//    std::string saveFilename = "cryptocontext.txt";

    // 创建监听套接字
    int listeningSocketFD = socket(AF_INET, SOCK_STREAM, 0);
    if (listeningSocketFD == -1) {
        std::cerr << "无法创建监听套接字" << std::endl;
        return 1;
    }

    // 设置本地地址信息
    sockaddr_in localAddress{};
    localAddress.sin_family = AF_INET;
    localAddress.sin_addr.s_addr = INADDR_ANY;
    localAddress.sin_port = htons(listeningPort);

    // 绑定监听套接字到本地地址
    if (bind(listeningSocketFD, (struct sockaddr*)&localAddress, sizeof(localAddress)) < 0) {
        std::cerr << "绑定套接字失败" << std::endl;
        return 1;
    }

    // 开始监听
    if (listen(listeningSocketFD, 1) < 0) {
        std::cerr << "开始监听失败" << std::endl;
        return 1;
    }

    std::cout << "等待连接..." << std::endl;

    // 接受连接请求
    sockaddr_in clientAddress{};
    socklen_t clientAddressLength = sizeof(clientAddress);
    int connectionSocketFD = accept(listeningSocketFD, (struct sockaddr*)&clientAddress, &clientAddressLength);
    if (connectionSocketFD < 0) {
        std::cerr << "接受连接失败" << std::endl;
        return 1;
    }

    std::cout << "已连接" << std::endl;

    // 创建文件来保存接收的数据
    std::ofstream outputFile(saveFilename);
    if (!outputFile) {
        std::cerr << "无法创建文件:" << saveFilename << std::endl;
        return 1;
    }

    // 接收数据并写入文件

    char buffer[BUFFER_SIZE];
    ssize_t bytesRead;
    while ((bytesRead = recv(connectionSocketFD, buffer, BUFFER_SIZE, 0)) > 0) {
        // 写入文件
        outputFile.write(buffer, bytesRead);
    }

//    char buffer[BUFFER_SIZE];
//    int bytesRead;
//    while ((bytesRead = recv(connectionSocketFD, buffer, BUFFER_SIZE, 0)) > 0) {
//        // 写入文件
//        outputFile.write(buffer, bytesRead);
//    }

    // 关闭套接字和文件
    close(connectionSocketFD);
    close(listeningSocketFD);
    outputFile.close();

    std::cout << "文件接收完成" << std::endl;

    return 0;
}

int send(int serverPort, std::string serverIP, std::string filename){
//    std::string serverIP = "192.168.1.103";
//    int serverPort = 12345;
//    std::string filename = "demoData/cryptocontext.txt";

    // 打开文件
    std::ifstream file(filename);
    if (!file) {
        std::cerr << "无法打开文件:" << filename << std::endl;
        return 1;
    }

    // 创建套接字
    int socketFD = socket(AF_INET, SOCK_STREAM, 0);
    if (socketFD == -1) {
        std::cerr << "无法创建套接字" << std::endl;
        return 1;
    }

    // 设置目标服务器的地址信息
    sockaddr_in serverAddress{};
    serverAddress.sin_family = AF_INET;
    serverAddress.sin_port = htons(serverPort);
    if (inet_pton(AF_INET, serverIP.c_str(), &(serverAddress.sin_addr)) <= 0) {
        std::cerr << "无效的IP地址:" << serverIP << std::endl;
        return 1;
    }

    // 连接到目标服务器

    int i = 0;
    for ( ; i < 50; ++i) {
        if (connect(socketFD, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) < 0) {
            std::cerr << "尝试连接失败,继续等待" << std::endl;
            sleep(1);
        }
        else break;
    }
    if (i == 5)
        return 1;

//    if (connect(socketFD, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) < 0) {
//        std::cerr << "连接失败" << std::endl;
//        return 1;
//    }

//    if (!connectWithTimeout(socketFD, (struct sockaddr*)&serverAddress, sizeof(serverAddress), 5)) {
//        std::cerr << "连接到目标主机失败" << std::endl;
//        return 1;
//    }

    // 逐行读取文件并发送数据

    char buffer[BUFFER_SIZE];
    while (!file.eof()) {
        file.read(buffer, BUFFER_SIZE);
        ssize_t bytesRead = file.gcount();

        // 发送数据
        ssize_t bytesSent = send(socketFD, buffer, bytesRead, 0);
        if (bytesSent == -1) {
            std::cerr << "发送数据失败" << std::endl;
            break;
        }
    }

    // 关闭套接字和文件
    close(socketFD);
    file.close();

    std::cout << "文件发送完成" << std::endl;

    return 0;
}

int main() {
//    auto start = std::chrono::high_resolution_clock::now();
//    usint batchSize = 16;

    receive(10305, DATAFOLDER + "/cryptocontext.txt");

    CryptoContext <DCRTPoly> cc;

    if (!Serial::DeserializeFromFile(DATAFOLDER + "/cryptocontext.txt", cc, SerType::BINARY)) {
        std::cerr << "I cannot read serialization from " << DATAFOLDER + "/cryptocontext.txt" << std::endl;
        return 1;
    }
    std::cout << "The cryptocontext has been deserialized." << std::endl;

    ////////////////////////////////////////////////////////////
    // Set-up of parameters
    ////////////////////////////////////////////////////////////

    // Output the generated parameters

    std::cout << "p = " << cc->GetCryptoParameters()->GetPlaintextModulus() << std::endl;
    std::cout << "n = " << cc->GetCryptoParameters()->GetElementParams()->GetCyclotomicOrder() / 2 << std::endl;
    std::cout << "log2 q = " << log2(cc->GetCryptoParameters()->GetElementParams()->GetModulus().ConvertToDouble())
              << std::endl;

    cc->Enable(PKE);
    cc->Enable(KEYSWITCH);
    cc->Enable(LEVELEDSHE);
    cc->Enable(ADVANCEDSHE);
    cc->Enable(MULTIPARTY);

    // Initialize Public Key Containers for two parties A and B

    receive(103052, DATAFOLDER + "/publickey1.txt");

    PublicKey <DCRTPoly> pk1;
    if (Serial::DeserializeFromFile(DATAFOLDER + "/publickey1.txt", pk1, SerType::BINARY) == false) {
        std::cerr << "Could not read publickey1" << std::endl;
        return 1;
    }
    std::cout << "The publickey1 has been deserialized." << std::endl;

    KeyPair <DCRTPoly> kp_2;

    kp_2 = cc->MultipartyKeyGen(pk1);

    // Serialize the public key
    if (!Serial::SerializeToFile(DATAFOLDER + "/publickey2.txt", kp_2.publicKey, SerType::BINARY)) {
        std::cerr << "Error writing serialization of public key2 to publickey2.txt" << std::endl;
        return 1;
    }
    std::cout << "The public-key2 has been serialized." << std::endl;

    send(10506, "192.168.1.106", DATAFOLDER + "/publickey2.txt");

    ////////////////////////////////////////////////////////////
    // Perform Key Generation Operation
    ////////////////////////////////////////////////////////////

    std::cout << "Running key generation (used for source data)..." << std::endl;

    // Round 1 (party A)

    // Generate evalmult key part for A
    receive(10305, DATAFOLDER + "/evalMultKey.txt");

    EvalKey <DCRTPoly> evalMultKey;
    if (Serial::DeserializeFromFile(DATAFOLDER + "/evalMultKey.txt", evalMultKey, SerType::BINARY) == false) {
        std::cerr << "Could not read evalMultKey" << std::endl;
        return 1;
    }
    std::cout << "The evalMultKey has been deserialized." << std::endl;

    auto evalMultKey2 = cc->MultiKeySwitchGen(kp_2.secretKey, kp_2.secretKey, evalMultKey);

    auto evalMultAB = cc->MultiAddEvalKeys(evalMultKey, evalMultKey2, kp_2.publicKey->GetKeyTag());

    if (!Serial::SerializeToFile(DATAFOLDER + "/evalMultAB.txt", evalMultAB, SerType::BINARY)) {
        std::cerr << "Error writing serialization of evalMultAB to evalMultAB.txt" << std::endl;
        return 1;
    }
    std::cout << "The evalMultAB has been serialized." << std::endl;

    send(10506, "192.168.1.106", DATAFOLDER + "/evalMultAB.txt");

    receive(10605, DATAFOLDER + "/evalMultABC.txt");

    EvalKey <DCRTPoly> evalMultABC;
    if (Serial::DeserializeFromFile(DATAFOLDER + "/evalMultABC.txt", evalMultABC, SerType::BINARY) == false) {
        std::cerr << "Could not read evalMultABC" << std::endl;
        return 1;
    }
    std::cout << "The evalMultABC has been deserialized." << std::endl;

    receive(10605, DATAFOLDER + "/publickey3.txt");

    PublicKey <DCRTPoly> pk3;
    if (Serial::DeserializeFromFile(DATAFOLDER + "/publickey3.txt", pk3, SerType::BINARY) == false) {
        std::cerr << "Could not read publickey3" << std::endl;
        return 1;
    }
    std::cout << "The public key3 has been deserialized." << std::endl;

    auto evalMultBABC = cc->MultiMultEvalKey(kp_2.secretKey, evalMultABC, pk3->GetKeyTag());

    if (!Serial::SerializeToFile(DATAFOLDER + "/evalMultBABC.txt", evalMultBABC, SerType::BINARY)) {
        std::cerr << "Error writing serialization of evalMultBABC to evalMultBABC.txt" << std::endl;
        return 1;
    }
    std::cout << "The evalMultBABC has been serialized." << std::endl;

    send(10506, "192.168.1.106", DATAFOLDER + "/evalMultBABC.txt");

    receive(10605, DATAFOLDER + "/evalMultFinal.txt");

    cc->ClearEvalMultKeys();

    std::ifstream emkeys3(DATAFOLDER + "/evalMultFinal.txt", std::ios::in | std::ios::binary);
    if (!emkeys3.is_open()) {
        std::cerr << "I cannot read serialization from " << DATAFOLDER + "/evalMultFinal.txt" << std::endl;
        return 1;
    }
    if (cc->DeserializeEvalMultKey(emkeys3, SerType::BINARY) == false) {
        std::cerr << "Could not deserialize the evalMultFinal file" << std::endl;
        return 1;
    }
    std::cout << "Deserialized the evalMultFinal." << std::endl;

    const auto evalMultFinal_p = cc->GetAllEvalMultKeys().begin();

    auto evalMultFinal = (*evalMultFinal_p).second[0];

    cc->InsertEvalMultKey({evalMultFinal});

    //---------------------------------------------------
    std::cout << "Running evalsum key generation (used for source data)..." << std::endl;

    // Generate evalsum key part for A

    receive(10305, DATAFOLDER + "/evalSumKeys.txt");

    std::shared_ptr < std::map < unsigned int, std::shared_ptr < lbcrypto::EvalKeyImpl < lbcrypto::DCRTPolyImpl <
                                               bigintdyn::mubintvec < bigintdyn::ubint < unsigned int > > > > >,
            std::less < unsigned int >, std::allocator < std::pair<const unsigned int,
            std::shared_ptr < lbcrypto::EvalKeyImpl < lbcrypto::DCRTPolyImpl < bigintdyn::mubintvec < bigintdyn::ubint <
            unsigned int> > > > > > > > > evalSumKeys;
    if (Serial::DeserializeFromFile(DATAFOLDER + "/evalSumKeys.txt", evalSumKeys, SerType::BINARY) == false) {
        std::cerr << "Could not read evalSumKeys" << std::endl;
        return 1;
    }
    std::cout << "The evalSumKeys has been deserialized." << std::endl;

    auto evalSumKeysB = cc->MultiEvalSumKeyGen(kp_2.secretKey, evalSumKeys, kp_2.publicKey->GetKeyTag());

    if (!Serial::SerializeToFile(DATAFOLDER + "/evalSumKeysB.txt", evalSumKeysB, SerType::BINARY)) {
        std::cerr << "Error writing serialization of public key to evalSumKeys.txt" << std::endl;
        return 1;
    }
    std::cout << "The evalSumKeysB has been serialized." << std::endl;

    send(10506, "192.168.1.106", DATAFOLDER + "/evalSumKeysB.txt");

    std::cout << "The eval sum keys have been generated." << std::endl;

    // Serialize the relinearization (evaluation) key for homomorphic
    // multiplication

    ////////////////////////////////////////////////////////////
    // Encode source data
    ////////////////////////////////////////////////////////////
    std::vector<double> vectorOfInts2 = {1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0};


    Plaintext plaintext2 = cc->MakeCKKSPackedPlaintext(vectorOfInts2);

    ////////////////////////////////////////////////////////////
    // Encryption
    ////////////////////////////////////////////////////////////

    Ciphertext <DCRTPoly> ciphertext2;

    ciphertext2 = cc->Encrypt(pk3, plaintext2);

    if (!Serial::SerializeToFile(DATAFOLDER + "/" + "ciphertext2.txt", ciphertext2, SerType::BINARY)) {
        std::cerr << "Error writing serialization of ciphertext 2 to ciphertext1.txt" << std::endl;
        return 1;
    }
    std::cout << "The second ciphertext has been serialized." << std::endl;

    send(105063, "192.168.1.106", DATAFOLDER + "/" + "ciphertext2.txt");

    ////////////////////////////////////////////////////////////
    // EvalAdd Operation on Re-Encrypted Data
    ////////////////////////////////////////////////////////////

    /*Function for evaluating a sum of all components
    Parameters
    ciphertext  C the input ciphertext.
    batchSize  C size of the batch
    Returns
    resulting ciphertext*/

    ////////////////////////////////////////////////////////////
    // Decryption after Accumulation Operation on Encrypted Data with Multiparty
    ////////////////////////////////////////////////////////////

    Plaintext plaintextAddNew2;

    DCRTPoly partialPlaintext2;

    Plaintext plaintextMultipartyNew;

    // distributed decryption

    receive(10605, DATAFOLDER + "/" + "ciphertextAdd123.txt");

    Ciphertext <DCRTPoly> ciphertextAdd123;
    if (Serial::DeserializeFromFile(DATAFOLDER + "/ciphertextAdd123.txt", ciphertextAdd123, SerType::BINARY) == false) {
        std::cerr << "Could not read the ciphertextAdd123" << std::endl;
        return 1;
    }
    std::cout << "The ciphertextAdd123  has been deserialized." << std::endl;

    auto sumciphertextPartial2_v = cc->MultipartyDecryptMain({ciphertextAdd123}, kp_2.secretKey);

    Ciphertext <DCRTPoly> sumciphertextPartial2 = sumciphertextPartial2_v[0];

    if (!Serial::SerializeToFile(DATAFOLDER + "/" + "sumciphertextPartial2.txt", sumciphertextPartial2,
                                 SerType::BINARY)) {
        std::cerr << "Error writing serialization of sumciphertextPartial2 to sumciphertextPartial2.txt" << std::endl;
        return 1;
    }
    std::cout << "The sumciphertextPartial2 has been serialized." << std::endl;

    send(10506, "192.168.1.106", DATAFOLDER + "/" + "sumciphertextPartial2.txt");

    receive(10605, DATAFOLDER + "/" + "ciphertextMult.txt");

    Ciphertext <DCRTPoly> ciphertextMult;
    if (Serial::DeserializeFromFile(DATAFOLDER + "/ciphertextMult.txt", ciphertextMult, SerType::BINARY) == false) {
        std::cerr << "Could not read the ciphertextMult" << std::endl;
        return 1;
    }
    std::cout << "The ciphertextMult  has been deserialized." << std::endl;

    auto multciphertextPartial2_v = cc->MultipartyDecryptMain({ciphertextMult}, kp_2.secretKey);

    Ciphertext <DCRTPoly> multciphertextPartial2 = multciphertextPartial2_v[0];

    if (!Serial::SerializeToFile(DATAFOLDER + "/" + "multciphertextPartial2.txt", multciphertextPartial2,
                                 SerType::BINARY)) {
        std::cerr << "Error writing serialization of multciphertextPartial2 to multciphertextPartial2.txt" << std::endl;
        return 1;
    }
    std::cout << "The multciphertextPartial2 has been serialized." << std::endl;

    send(10506, "192.168.1.106", DATAFOLDER + "/" + "multciphertextPartial2.txt");

}

This is the code for node C

#include "openfhe.h"
#include <iostream>
#include <algorithm>
#include <vector>
#include <chrono>
#include <fstream>
#include <string>
#include <cstring>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <functional>
#include <map>
#include <memory>
#include <utility>
//#include "pybind11/pybind11.h"
//#include "pybind11/stl.h"
//namespace py = pybind11;

// header files needed for serialization
#include "ciphertext-ser.h"
#include "cryptocontext-ser.h"
#include "key/key-ser.h"
#include "scheme/ckksrns/ckksrns-ser.h"

#define BUFFER_SIZE 4096

using namespace std;
using namespace lbcrypto;

const std::string DATAFOLDER = "demoData3";

int receive(int listeningPort, std::string saveFilename){
//    int listeningPort = 12345;
//    std::string saveFilename = "cryptocontext.txt";

    // 创建监听套接字
    int listeningSocketFD = socket(AF_INET, SOCK_STREAM, 0);
    if (listeningSocketFD == -1) {
        std::cerr << "无法创建监听套接字" << std::endl;
        return 1;
    }

    // 设置本地地址信息
    sockaddr_in localAddress{};
    localAddress.sin_family = AF_INET;
    localAddress.sin_addr.s_addr = INADDR_ANY;
    localAddress.sin_port = htons(listeningPort);

    // 绑定监听套接字到本地地址
    if (bind(listeningSocketFD, (struct sockaddr*)&localAddress, sizeof(localAddress)) < 0) {
        std::cerr << "绑定套接字失败" << std::endl;
        return 1;
    }

    // 开始监听
    if (listen(listeningSocketFD, 1) < 0) {
        std::cerr << "开始监听失败" << std::endl;
        return 1;
    }

    std::cout << "等待连接..." << std::endl;

    // 接受连接请求
    sockaddr_in clientAddress{};
    socklen_t clientAddressLength = sizeof(clientAddress);
    int connectionSocketFD = accept(listeningSocketFD, (struct sockaddr*)&clientAddress, &clientAddressLength);
    if (connectionSocketFD < 0) {
        std::cerr << "接受连接失败" << std::endl;
        return 1;
    }

    std::cout << "已连接" << std::endl;

    // 创建文件来保存接收的数据
    std::ofstream outputFile(saveFilename);
    if (!outputFile) {
        std::cerr << "无法创建文件:" << saveFilename << std::endl;
        return 1;
    }

    // 接收数据并写入文件

    char buffer[BUFFER_SIZE];
    ssize_t bytesRead;
    while ((bytesRead = recv(connectionSocketFD, buffer, BUFFER_SIZE, 0)) > 0) {
        // 写入文件
        outputFile.write(buffer, bytesRead);
    }

//    char buffer[BUFFER_SIZE];
//    int bytesRead;
//    while ((bytesRead = recv(connectionSocketFD, buffer, BUFFER_SIZE, 0)) > 0) {
//        // 写入文件
//        outputFile.write(buffer, bytesRead);
//    }

    // 关闭套接字和文件
    close(connectionSocketFD);
    close(listeningSocketFD);
    outputFile.close();

    std::cout << "文件接收完成" << std::endl;

    return 0;
}

int send(int serverPort, std::string serverIP, std::string filename){
//    std::string serverIP = "192.168.1.103";
//    int serverPort = 12345;
//    std::string filename = "demoData/cryptocontext.txt";

    // 打开文件
    std::ifstream file(filename);
    if (!file) {
        std::cerr << "无法打开文件:" << filename << std::endl;
        return 1;
    }

    // 创建套接字
    int socketFD = socket(AF_INET, SOCK_STREAM, 0);
    if (socketFD == -1) {
        std::cerr << "无法创建套接字" << std::endl;
        return 1;
    }

    // 设置目标服务器的地址信息
    sockaddr_in serverAddress{};
    serverAddress.sin_family = AF_INET;
    serverAddress.sin_port = htons(serverPort);
    if (inet_pton(AF_INET, serverIP.c_str(), &(serverAddress.sin_addr)) <= 0) {
        std::cerr << "无效的IP地址:" << serverIP << std::endl;
        return 1;
    }

    // 连接到目标服务器

    int i = 0;
    for ( ; i < 50; ++i) {
        if (connect(socketFD, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) < 0) {
            std::cerr << "尝试连接失败,继续等待" << std::endl;
            sleep(1);
        }
        else break;
    }
    if (i == 5)
        return 1;

//    if (connect(socketFD, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) < 0) {
//        std::cerr << "连接失败" << std::endl;
//        return 1;
//    }

//    if (!connectWithTimeout(socketFD, (struct sockaddr*)&serverAddress, sizeof(serverAddress), 5)) {
//        std::cerr << "连接到目标主机失败" << std::endl;
//        return 1;
//    }

    // 逐行读取文件并发送数据

    char buffer[BUFFER_SIZE];
    while (!file.eof()) {
        file.read(buffer, BUFFER_SIZE);
        ssize_t bytesRead = file.gcount();

        // 发送数据
        ssize_t bytesSent = send(socketFD, buffer, bytesRead, 0);
        if (bytesSent == -1) {
            std::cerr << "发送数据失败" << std::endl;
            break;
        }
    }

//    std::string line;
//    while (std::getline(file, line)) {
//        // 发送数据
//        if (send(socketFD, line.c_str(), line.length(), 0) == -1) {
//            std::cerr << "发送数据失败" << std::endl;
//            return 1;
//        }
//    }

    // 关闭套接字和文件
    close(socketFD);
    file.close();

    std::cout << "文件发送完成" << std::endl;

    return 0;
}

int main() {

    receive(10306, DATAFOLDER + "/cryptocontext.txt");

    CryptoContext<DCRTPoly> cc;

    if (!Serial::DeserializeFromFile(DATAFOLDER + "/cryptocontext.txt", cc, SerType::BINARY)) {
        std::cerr << "I cannot read serialization from " << DATAFOLDER + "/cryptocontext.txt" << std::endl;
        return 1;
    }
    std::cout << "The cryptocontext has been deserialized." << std::endl;

    ////////////////////////////////////////////////////////////
    // Set-up of parameters
    ////////////////////////////////////////////////////////////

    // Output the generated parameters

    std::cout << "p = " << cc->GetCryptoParameters()->GetPlaintextModulus() << std::endl;
    std::cout << "n = " << cc->GetCryptoParameters()->GetElementParams()->GetCyclotomicOrder() / 2 << std::endl;
    std::cout << "log2 q = " << log2(cc->GetCryptoParameters()->GetElementParams()->GetModulus().ConvertToDouble())
              << std::endl;

    cc->Enable(PKE);
    cc->Enable(KEYSWITCH);
    cc->Enable(LEVELEDSHE);
    cc->Enable(ADVANCEDSHE);
    cc->Enable(MULTIPARTY);

    // Initialize Public Key Containers for two parties A and B
    receive(10506, DATAFOLDER + "/publickey2.txt");

    PublicKey<DCRTPoly> pk2;
    if (Serial::DeserializeFromFile(DATAFOLDER + "/publickey2.txt", pk2, SerType::BINARY) == false) {
        std::cerr << "Could not read publickey2" << std::endl;
        return 1;
    }
    std::cout << "The publickey2 has been deserialized." << std::endl;

    auto kp_3 = cc->MultipartyKeyGen(pk2);

//    auto start_multkeygen = std::chrono::high_resolution_clock::now();
    // Generate evalmult key part for A
    receive(10306, DATAFOLDER + "/evalMultKey.txt");

    EvalKey<DCRTPoly> evalMultKey;
    if (Serial::DeserializeFromFile(DATAFOLDER + "/evalMultKey.txt", evalMultKey, SerType::BINARY) == false) {
        std::cerr << "Could not read evalMultKey" << std::endl;
        return 1;
    }
    std::cout << "The evalMultKey has been deserialized." << std::endl;

    auto evalMultKey3 = cc->MultiKeySwitchGen(kp_3.secretKey, kp_3.secretKey, evalMultKey);

    receive(10506, DATAFOLDER + "/evalMultAB.txt");

    EvalKey<DCRTPoly> evalMultAB;
    if (Serial::DeserializeFromFile(DATAFOLDER + "/evalMultAB.txt", evalMultAB, SerType::BINARY) == false) {
        std::cerr << "Could not read evalMultAB" << std::endl;
        return 1;
    }
    std::cout << "The evalMultAB has been deserialized." << std::endl;

    auto evalMultABC = cc->MultiAddEvalKeys(evalMultAB, evalMultKey3, kp_3.publicKey->GetKeyTag());

    if (!Serial::SerializeToFile(DATAFOLDER + "/evalMultABC.txt", evalMultABC, SerType::BINARY)) {
        std::cerr << "Error writing serialization of evalMultABC to evalMultABC.txt" << std::endl;
        return 1;
    }
    std::cout << "The evalMultABC has been serialized." << std::endl;

    send(10603, "192.168.1.103", DATAFOLDER + "/evalMultABC.txt");
    send(10605, "192.168.1.105", DATAFOLDER + "/evalMultABC.txt");

    // Serialize the public key
    if (!Serial::SerializeToFile(DATAFOLDER + "/publickey3.txt", kp_3.publicKey, SerType::BINARY)) {
        std::cerr << "Error writing serialization of public key to keypublic3.txt" << std::endl;
        return 1;
    }
    std::cout << "The publickey3 has been serialized." << std::endl;

    send(10603, "192.168.1.103", DATAFOLDER + "/publickey3.txt");
    send(10605, "192.168.1.105", DATAFOLDER + "/publickey3.txt");

    auto evalMultCABC = cc->MultiMultEvalKey(kp_3.secretKey, evalMultABC, kp_3.publicKey->GetKeyTag());

    receive(10506, DATAFOLDER + "/evalMultBABC.txt");

    EvalKey<DCRTPoly> evalMultBABC;
    if (Serial::DeserializeFromFile(DATAFOLDER + "/evalMultBABC.txt", evalMultBABC, SerType::BINARY) == false) {
        std::cerr << "Could not read evalMultBABC" << std::endl;
        return 1;
    }
    std::cout << "The evalMultBABC has been deserialized." << std::endl;

    auto evalMultBCABC = cc->MultiAddEvalMultKeys(evalMultCABC, evalMultBABC, evalMultCABC->GetKeyTag());

    receive(10306, DATAFOLDER + "/evalMultAABC.txt");

    EvalKey<DCRTPoly> evalMultAABC;
    if (Serial::DeserializeFromFile(DATAFOLDER + "/evalMultAABC.txt", evalMultAABC, SerType::BINARY) == false) {
        std::cerr << "Could not read evalMultAABC" << std::endl;
        return 1;
    }
    std::cout << "The evalMultAABC has been deserialized." << std::endl;

    auto evalMultFinal = cc->MultiAddEvalMultKeys(evalMultAABC, evalMultBCABC, kp_3.publicKey->GetKeyTag());

    cc->InsertEvalMultKey({evalMultFinal});

    std::cout << "The evalMultFinal have been generated." << std::endl;

    // Serialize the relinearization (evaluation) key for homomorphic    // multiplication
    std::ofstream emkeyfile2(DATAFOLDER + "/" + "evalMultFinal.txt", std::ios::out | std::ios::binary);
    if (emkeyfile2.is_open()) {
        if (cc->SerializeEvalMultKey(emkeyfile2, SerType::BINARY) == false) {
            std::cerr << "Error writing serialization of the eval mult keys to "
                         "evalMultFinal.txt"
                      << std::endl;
            return 1;
        }
        std::cout << "The evalMultFinal have been serialized." << std::endl;

        emkeyfile2.close();
    }
    else {
        std::cerr << "Error serializing evalMultFinal" << std::endl;
        return 1;
    }

    send(10603, "192.168.1.103", DATAFOLDER + "/evalMultFinal.txt");
    send(10605, "192.168.1.105", DATAFOLDER + "/evalMultFinal.txt");

    //---------------------------------------------------
    std::cout << "Running evalsum key generation (used for source data)..." << std::endl;
    // Generate evalsum key part for A

    receive(10306, DATAFOLDER + "/evalSumKeys.txt");

    std::shared_ptr<std::map<unsigned int, std::shared_ptr<lbcrypto::EvalKeyImpl<lbcrypto::DCRTPolyImpl<bigintdyn::mubintvec<bigintdyn::ubint<unsigned int> > > > >, std::less<unsigned int>, std::allocator<std::pair<const unsigned int, std::shared_ptr<lbcrypto::EvalKeyImpl<lbcrypto::DCRTPolyImpl<bigintdyn::mubintvec<bigintdyn::ubint<unsigned int> > > > > > > > > evalSumKeys;

    if (Serial::DeserializeFromFile(DATAFOLDER + "/evalSumKeys.txt", evalSumKeys, SerType::BINARY) == false) {
        std::cerr << "Could not read evalSumKeys" << std::endl;
        return 1;
    }
    std::cout << "The evalSumKeys has been deserialized." << std::endl;

    auto evalSumKeysC = cc->MultiEvalSumKeyGen(kp_3.secretKey, evalSumKeys, kp_3.publicKey->GetKeyTag());

    receive(10506, DATAFOLDER + "/evalSumKeysB.txt");

    std::shared_ptr<std::map<unsigned int, std::shared_ptr<lbcrypto::EvalKeyImpl<lbcrypto::DCRTPolyImpl<bigintdyn::mubintvec<bigintdyn::ubint<unsigned int> > > > >, std::less<unsigned int>, std::allocator<std::pair<const unsigned int, std::shared_ptr<lbcrypto::EvalKeyImpl<lbcrypto::DCRTPolyImpl<bigintdyn::mubintvec<bigintdyn::ubint<unsigned int> > > > > > > > > evalSumKeysB;

    if (Serial::DeserializeFromFile(DATAFOLDER + "/evalSumKeysB.txt", evalSumKeysB, SerType::BINARY) == false) {
        std::cerr << "Could not read evalSumKeysB" << std::endl;
        return 1;
    }
    std::cout << "The evalSumKeysB has been deserialized." << std::endl;

    auto evalSumKeysAB = cc->MultiAddEvalSumKeys(evalSumKeys, evalSumKeysB, pk2->GetKeyTag());

    auto evalSumKeysJoin = cc->MultiAddEvalSumKeys(evalSumKeysC, evalSumKeysAB, kp_3.publicKey->GetKeyTag());

    cc->InsertEvalSumKey(evalSumKeysJoin);

    std::cout << "The eval sum keys have been generated." << std::endl;

//    auto end_sumkeygen = std::chrono::high_resolution_clock::now();
    ////////////////////////////////////////////////////////////
    // Encode source data
    ////////////////////////////////////////////////////////////
    std::vector<double> vectorOfInts3 = {2, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0};

    Plaintext plaintext3 = cc->MakeCKKSPackedPlaintext(vectorOfInts3);

    ////////////////////////////////////////////////////////////
    // Encryption
    ////////////////////////////////////////////////////////////

    Ciphertext<DCRTPoly> ciphertext3;
//    Ciphertext<DCRTPoly> ciphertext4;//new

    ciphertext3 = cc->Encrypt(kp_3.publicKey, plaintext3);

    if (!Serial::SerializeToFile(DATAFOLDER + "/" + "ciphertext3.txt", ciphertext3, SerType::BINARY)) {
        std::cerr << "Error writing serialization of ciphertext 3 to ciphertext3.txt" << std::endl;
        return 1;
    }
    std::cout << "The first ciphertext has been serialized." << std::endl;

    receive(103063, DATAFOLDER + "/" + "ciphertext1.txt");

    Ciphertext<DCRTPoly> ciphertext1;
    if (Serial::DeserializeFromFile(DATAFOLDER + "/ciphertext1.txt", ciphertext1, SerType::BINARY) == false) {
        std::cerr << "Could not read the ciphertext1" << std::endl;
        return 1;
    }
    std::cout << "The first ciphertext 1 has been deserialized." << std::endl;

    Ciphertext<DCRTPoly> ciphertext2;

    receive(105063, DATAFOLDER + "/" + "ciphertext2.txt");

    if (Serial::DeserializeFromFile(DATAFOLDER + "/ciphertext2.txt", ciphertext2, SerType::BINARY) == false) {
        std::cerr << "Could not read the ciphertext2" << std::endl;
        return 1;
    }
    std::cout << "The second ciphertext 2 has been deserialized." << std::endl;


    ////////////////////////////////////////////////////////////
    // EvalAdd Operation on Re-Encrypted Data
    ////////////////////////////////////////////////////////////

    Ciphertext<DCRTPoly> ciphertextAdd12;
    Ciphertext<DCRTPoly> ciphertextAdd123;

    ciphertextAdd12  = cc->EvalAdd(ciphertext1, ciphertext2);
    ciphertextAdd123 = cc->EvalAdd(ciphertextAdd12, ciphertext3);

    auto ciphertextMult = cc->EvalMult(ciphertext1, ciphertext3);

    ////////////////////////////////////////////////////////////
    // Decryption after Accumulation Operation on Encrypted Data with Multiparty
    ////////////////////////////////////////////////////////////

    Plaintext plaintextAddNew1;
    Plaintext plaintextAddNew2;
    Plaintext plaintextAddNew3;

    DCRTPoly partialPlaintext1;
    DCRTPoly partialPlaintext2;
    DCRTPoly partialPlaintext3;

    Plaintext plaintextMultipartyNew;

    // distributed decryption

    if (!Serial::SerializeToFile(DATAFOLDER + "/" + "ciphertextAdd123.txt", ciphertextAdd123, SerType::BINARY)) {
        std::cerr << "Error writing serialization of ciphertextAdd123 to ciphertextAdd123.txt" << std::endl;
        return 1;
    }
    std::cout << "The ciphertextAdd123 has been serialized." << std::endl;

    send(10603, "192.168.1.103", DATAFOLDER + "/" + "ciphertextAdd123.txt");
    send(10605, "192.168.1.105", DATAFOLDER + "/" + "ciphertextAdd123.txt");

    receive(10306, DATAFOLDER + "/" + "sumciphertextPartial1.txt");

    Ciphertext<DCRTPoly> sumciphertextPartial1;
    if (Serial::DeserializeFromFile(DATAFOLDER + "/sumciphertextPartial1.txt", sumciphertextPartial1, SerType::BINARY) == false) {
        std::cerr << "Could not read the sumciphertextPartial1" << std::endl;
        return 1;
    }
    std::cout << "The sumciphertextPartial1  has been deserialized." << std::endl;

    receive(10506, DATAFOLDER + "/" + "sumciphertextPartial2.txt");

    Ciphertext<DCRTPoly> sumciphertextPartial2;
    if (Serial::DeserializeFromFile(DATAFOLDER + "/sumciphertextPartial2.txt", sumciphertextPartial2, SerType::BINARY) == false) {
        std::cerr << "Could not read the sumciphertextPartial2" << std::endl;
        return 1;
    }
    std::cout << "The sumciphertextPartial2  has been deserialized." << std::endl;

    auto sumciphertextPartial3 = cc->MultipartyDecryptMain({ciphertextAdd123}, kp_3.secretKey);

    std::vector<Ciphertext<DCRTPoly>> partialCiphertextVec;
    partialCiphertextVec.push_back(sumciphertextPartial1);
    partialCiphertextVec.push_back(sumciphertextPartial2);
    partialCiphertextVec.push_back(sumciphertextPartial3[0]);

    cc->MultipartyDecryptFusion(partialCiphertextVec, &plaintextMultipartyNew);

    plaintextMultipartyNew->SetLength(plaintext3->GetLength());

    std::cout << "\n Resulting Fused Plaintext: \n" << std::endl;
    std::cout << plaintextMultipartyNew << std::endl;

    std::cout << "\n";

//    auto start_multdecrypt = std::chrono::high_resolution_clock::now();
    Plaintext plaintextMultipartyMult;

    if (!Serial::SerializeToFile(DATAFOLDER + "/" + "ciphertextMult.txt", ciphertextMult, SerType::BINARY)) {
        std::cerr << "Error writing serialization of ciphertextMult to ciphertextMult.txt" << std::endl;
        return 1;
    }
    std::cout << "The ciphertextMult has been serialized." << std::endl;

    send(10603, "192.168.1.103", DATAFOLDER + "/" + "ciphertextMult.txt");
    send(10605, "192.168.1.105", DATAFOLDER + "/" + "ciphertextMult.txt");

    receive(10306, DATAFOLDER + "/" + "multciphertextPartial1.txt");

    Ciphertext<DCRTPoly> multciphertextPartial1;
    if (Serial::DeserializeFromFile(DATAFOLDER + "/multciphertextPartial1.txt", multciphertextPartial1, SerType::BINARY) == false) {
        std::cerr << "Could not read the multciphertextPartial1" << std::endl;
        return 1;
    }
    std::cout << "The multciphertextPartial1  has been deserialized." << std::endl;

    receive(10506, DATAFOLDER + "/" + "multciphertextPartial2.txt");

    Ciphertext<DCRTPoly> multciphertextPartial2;
    if (Serial::DeserializeFromFile(DATAFOLDER + "/multciphertextPartial2.txt", multciphertextPartial2, SerType::BINARY) == false) {
        std::cerr << "Could not read the multciphertextPartial2" << std::endl;
        return 1;
    }
    std::cout << "The multciphertextPartial2  has been deserialized." << std::endl;

    auto multciphertextPartial3 = cc->MultipartyDecryptMain({ciphertextMult}, kp_3.secretKey);

    std::cout<<"ciphertextPartial1 NoiseScaleDeg is : "<<multciphertextPartial1->GetNoiseScaleDeg()<<std::endl;
    std::cout<<"ciphertextPartial1 ScalingFactor is : "<<multciphertextPartial1->GetScalingFactor()<<std::endl;
    std::cout<<"ciphertextPartial2 NoiseScaleDeg is : "<<multciphertextPartial2->GetNoiseScaleDeg()<<std::endl;
    std::cout<<"ciphertextPartial2 ScalingFactor is : "<<multciphertextPartial2->GetScalingFactor()<<std::endl;
    std::cout<<"ciphertextPartial3 NoiseScaleDeg is : "<<multciphertextPartial3[0]->GetNoiseScaleDeg()<<std::endl;
    std::cout<<"ciphertextPartial3 ScalingFactor is : "<<multciphertextPartial3[0]->GetScalingFactor()<<std::endl;

    std::cout << "3 fenbushijiemi meiwenti" << std::endl;

    std::vector<Ciphertext<DCRTPoly>> partialCiphertextVecMult;
    partialCiphertextVecMult.push_back(multciphertextPartial1);
    partialCiphertextVecMult.push_back(multciphertextPartial2);
    partialCiphertextVecMult.push_back(multciphertextPartial3[0]);

    cc->MultipartyDecryptFusion(partialCiphertextVecMult, &plaintextMultipartyMult);


    plaintextMultipartyMult->SetLength(plaintext3->GetLength());


    std::cout << "\n Resulting Fused Plaintext after Multiplication of plaintexts 1 "
                 "and 3: \n"
              << std::endl;
    std::cout << plaintextMultipartyMult << std::endl;

    std::cout << "\n";

    std::cout << "\n Fused result after the Summation of ciphertext 3: "//new
                 "\n"
              << std::endl;

}

Thank you very much for seeing my question amidst your busy schedule

Hi @yinyanshuai

It is really hard to debug the networked version w/o running it. At a high-level you probably have an issue generating one of the joint keys. If one of the keys is not correctly generated, you will get incorrect results (what you see in the output).

I suggest the following troubleshooting steps:

  1. Build a single-file cpp file with all operations. You can initially do it even w/o serialization (all in memory). If this example is incorrect, then you have a logical error. You could post this file here if this does not work (I cannot really debug a full networked application as it it not related to OpenFHE).
  2. If the simple file works, then probably wrong files get serialized/deserialized, or the sequence is incorrect. Careful debugging (step-by-step) by comparing with the single-file simple example should help. You can also set the FIXED_SEED in distributiongenerator.h and compile without OMP support (WITH_OPENMP flag) to get repeatable results.

Okay, I will try according to your suggestion. Thank you very much for your answer.