I need to generate ciphertext and temporary data between each steps of CKKS bootstrapping as .txt file. I used the following code:
std::ofstream ofs;
ofs.open("bootstrapInput.txt");
if (!ofs.is_open()) {
std::cout << "Failed to open file.\n";
throw std::invalid_argument("Error when opening .txt file.");
}
// get ciphertext elements
auto ciphertextElements = ciphertext->GetElements();
for (size_t i = 0; i < ciphertextElements.size(); i++)
ofs << ciphertextElements[i].GetElementAtIndex(0). << " " << ciphertextElements[i].GetElementAtIndex(1) << "\n";
It works but the .txt file also shows the type of output data, in my case, "EVAL: ".
I would like to remove it but couldnāt find the format setting. Is it possible to set the output format without these redundant information? Or is there a better way suggested to keep data as golden pattern?
If you want to print out (for logging/debugging purposes) the vectors for individual polynomials, you can call the GetValues() method (this is the method called in the code you referred to: openfhe-development/poly.h at v1.0.1 Ā· openfheorg/openfhe-development Ā· GitHub). You can add it to the GetElementAtIndex(0) as GetElementAtIndex(0).GetValues().
Serialize is implemented using the USC Cereal Library. It will capture ALL of the data associated with the crypto object (similar to a python pickle). You can save in json or binary form (binary is exact and smaller, json is ascii output of the data).
We decided to use this approach because it requires minimum recoding on our part if and when the internal data objects change structure.
I believe we specifically use a patched version hereto support some extensions we use such as 128 bit native ints.
I try to dump a binary .txt file and at the same time print the data on console, I assume that the .txt file generated will be hex format of output data on console (in order to make sure Iām generating the right data).
However, it seems the values are diffierent between .txt file and console.
Hi, the binary file is pure binary. Not hex. it is meant to be deserialized on the other end by another program (OpenFHE based). Iād suggest a ā.binā extension. It is not even ASCII it is just raw bits, it will not print to the screen. It is the most packed way of representation.
To be clear, you are wanting to look at the internal integer values of the ciphertext. You can double check but
the operator<< for the object you are looking at (that says Eval: )actually does not print out all the values, only the first nonzero values. It is really only to be used for quick debugging. So it is different that the output of the serialization, which contains all the data including zero values etc.
Got it, I tried 3 different ways to output data. The first one is through iteration, and it shows the result on the screen. The second one dumps the data out through Serialization in binary format, and the third one also uses Serialization but in .json format. All the result of mentioned methods are shown below.
output through iteration
code
for (size_t i = 0; i < ciphertextElements.size(); i++)
std::cout << "Polynomial " << i << " " << ciphertextElements[i] << std::endl;
I discovered that the values on screen could be found in json file, and both .bin and .json should be the same values but in different format.
I am trying to design a CKKS bootstrapping accelerator constructed of VHDL, and the temporary data between each step of bootstrap is needed for debugging.
Therefore, my goal is to output a bunch of .txt files which representing the changes of ciphertext between different steps of CKKS bootstrapping. For example, Iāll output a file after processing ModRaise, CoeffToSlot, SineEval, etc.
I need to know the output sequence of method 2 above so I could know how to get the correct values in VHDL. Is it possible to know such information?
Hi, if possible the first thing Iād suggest is work with very small ring sizes and # towers. It will not be secure. But a json result would be easily parsable by humans or sw. Then scale it up.
also, rather than examining an entire CT break it down into itās components and look at them. for example each tower is simply a vector of native integers. you can serialize those components, or even just write them to a file in a loop. Serialize/Deserialize also contains the information necessary to reconstruct an entire C++ object, and you probably do not want that (especially since we tend to store a DCRT poly as a vector of smart pointers + associated parameters. Focus instead on the core vectors you are processing in HW.