Skip to content

tutorial_hello

Renaud Sirdey edited this page Dec 21, 2017 · 3 revisions

Hello world application with Cingulata

This step-by-step tutorial is designed to guide you on how you can write a new application, configure it and make it optimized and run within Cingulata. You may also want to take a look at the different code examples, present in the tests/ directory.

By now, you have installed and configured the compilation chain and the runtime. You have a main directory named 'cingulata' and several sub-directories, including 'build' and 'tests'.

To create a new test "test-hello", go to the 'tests' sub-directory of 'cingulata' and create a new directory 'test-hello':

#!shell
cd tests/
mkdir test-hello

Inside this directory, you will write your source code 'test-hello.cxx' and the execution script 'run.sh'.

Let's create a new testing file named 'test-hello.cxx' doing the addition of two integers:


#!c++
/* compiler includes */
#include <iostream>
#include <fstream>

/* local includes */
#include <integer.hxx>

/* namespaces */
using namespace std;

int main()
{
	Integer8 a,b,c;

	cin>>a;
	cin>>b;
	
	c=a+b;

	cout<<c;
	
	FINALIZE_CIRCUIT("test-hello.blif");
}

As you can see, the two integers a and b are defined using the special type Integer8 and are read from the console. The result is a variable c of type Integer8 which will be displayed on the standard output. The final line specifies that the Boolean circuit associated with this input code will be saved in a file named "test-hello.blif".

Now, we will create the shell script 'run.sh' with the following content:

#!shell

#!/bin/bash

CURR_DIR=$PWD
FILE=test-hello

APPS_DIR=$CURR_DIR/../../apps/

mkdir -p input
rm -f input/*.ct

mkdir -p output
rm -f output/*.ct

# Generate keys
echo "FHE key generation"
time $APPS_DIR/generate_keys

echo "Input encryption"
NR_THREADS=1

$APPS_DIR/encrypt -v --public-key fhe_key.pk  --threads $NR_THREADS `$APPS_DIR/helper --bit-cnt 8 --msb-first --prefix input/i_ --idx-places 0 20 18`

echo "Homomorphic execution..."
time $APPS_DIR/dyn_omp $FILE'-opt.blif' --threads $NR_THREADS # -v 

echo "Output decryption"
OUT_FILES=`ls -v output/*`
$APPS_DIR/helper --from-bin --bit-cnt 8 --msb-first `$APPS_DIR/decrypt --secret-key fhe_key.sk $OUT_FILES`

This script creates two empty directories: 'input' and 'output' (or clean them if they were created before). It calls the binary 'generate_keys' to generate the binary files for the private, public and respectively the evaluation keys. The encryption of the two input variables is done bitwise, on 8 bits (--bit-cnt option) (remember they were defined as Integer8 in the input code), in most significant order first (msb-first option) using a given number of threads. The encrypted bits will be saved in the input directory as individual binary files with the prefix i_ starting from 'i_2' (the first two i_0 and i_1 names being allocated for the 0 and respectively 1 constants). The homomorphic execution is realized by calling the runtime 'dyn-omp' on the optimized circuit: 'test-hello-opt.blif' in parallel using $NR_THREADS. Finally, the result is decrypted by looking into the output directory, decrypt each bit and pack them in a 'nice' format using the "helper" script.

You're almost at the end but, before running the test, you will have to create a file 'CMakeLists.txt' into the directory 'test-hello'. Here is the content of it:

#!cmake

cmake_minimum_required(VERSION 3.5)

set(TEST_NAME test-hello)

set(SRCS 
    ${TEST_NAME}.cxx
    )

add_compile_options(-Wall -std=c++11)

set(GEN_NAME ${TEST_NAME}-gen)

add_executable(${GEN_NAME} ${SRCS}) 

set(BLIF_NAME ${TEST_NAME}.blif)
set(BLOP_NAME ${TEST_NAME}-opt.blif)

target_link_libraries(${GEN_NAME} generator)

add_custom_command(OUTPUT ${BLIF_NAME}
  COMMAND ./${GEN_NAME} < /dev/null
  DEPENDS ${GEN_NAME}) 

add_custom_command(OUTPUT ${BLOP_NAME}
  COMMAND bash ../../optim/abc_optimize.bash -i ${BLIF_NAME} -o ${BLOP_NAME} > /dev/null
  DEPENDS abc ${BLIF_NAME})


set(XML_PARAMS fhe_params.xml)
set(MUL_DEPTH_SCRIPT ../../optim/graph_info.py)
set(GEN_PARAM_SCRIPT ../../runtime/fhe_fv/script/genParams.py)

add_custom_command(OUTPUT ${XML_PARAMS}
  COMMAND python3 ${GEN_PARAM_SCRIPT} --lambda_p 128 --mult_depth `python3 ${MUL_DEPTH_SCRIPT} ${BLOP_NAME} --mult_depth_max` --cyclotomic_poly_order 512 --output_xml ${XML_PARAMS}
  DEPENDS ${BLOP_NAME})

set(LAST_DEPEND ${XML_PARAMS})

add_custom_target(${TEST_NAME} ALL
  DEPENDS ${LAST_DEPEND})

configure_file("run.sh" "run.sh" COPYONLY)

As you can see, at the beginning it specifies information about the C++ compilation options. Afterwards, it calls 'ABC' for the optimization of the initial 'test-hello.blif' which results in the creation of a new blif file named 'test-hello-opt.blif'. The parameters of FHE schemes are specified in the XML file: 'fhe_params.xml' and are generated though a python3 script, taking as input different options such as the multiplicate depth, the order of the cyclotomic polynomial, the security parameter 'lambda_p', etc.

Note 1: The script for generating FHE parameters is now configured for Fan-Vercauteren original scheme.

Note 2: The script python 'graph_info.py' analyses the Boolean circuit specified as a .blif file and gives information about the size of the circuit, the number of particular gates (AND and XOR),the maximal multiplicative depth, etc.

Note 3: The 'CMakeLists.txt' file is very similar from a test to another. You can just copy one from an existing test and slightly modify it, by setting the right test name:

#!cmake
set(TEST_NAME test-hello) 

Once you wrote your 'CMakeLists.txt' file in the directory 'test-hello', you have to add this directory to the general 'CMakeLists' from the 'test' directory:

#!cmake

cmake_minimum_required(VERSION 3.5)

project(tests)
...
add_subdirectory(test-hello)

Note 4: In order to avoid to compile the other tests, you may want to comment the associated lines from the CMakeLists file. For example, to remove 'hello' test, just comment the line:

#!cmake
#add_subdirectory(hello)

That's all for the configuration of the application. All you have to do now is to compile and run it. For this, you have to go to the 'build' directory and run:

#!shell

cd ../build/
cmake
make -j 8

At the end, in 'build' a new directory named 'test-hello' is created containing all the necessary files and executables for running the test (the xml file with the FHE parameters, the blif files - the original and optimized one, the script 'run.sh', etc.). In the example we have compiled using 8 parallel jobs but you can specify a different number.

Now, you can finally execute your first application with Cingulata:

#!shell
cd tests/test-hello/
bash run.sh

If all went well, you can see in the terminal all the steps: the key generation, the encryption (bit by bit), the execution details, and the output result:

#!shell
FHE key generation
0.08user 0.05system 0:00.15elapsed 88%CPU (0avgtext+0avgdata 10624maxresident)k
5136inputs+1848outputs (20major+1519minor)pagefaults 0swaps
Input encryption
Command line arguments:
FHE parameters file fhe_params.xml
Public key file fhe_key.pk
Encrypting message [0] into file input/i_2.ct
Encrypting message [0] into file input/i_3.ct
Encrypting message [0] into file input/i_4.ct
Encrypting message [1] into file input/i_5.ct
Encrypting message [0] into file input/i_6.ct
Encrypting message [1] into file input/i_7.ct
Encrypting message [0] into file input/i_8.ct
Encrypting message [0] into file input/i_9.ct
Encrypting message [0] into file input/i_10.ct
Encrypting message [0] into file input/i_11.ct
Encrypting message [0] into file input/i_12.ct
Encrypting message [1] into file input/i_13.ct
Encrypting message [0] into file input/i_14.ct
Encrypting message [0] into file input/i_15.ct
Encrypting message [1] into file input/i_16.ct
Encrypting message [0] into file input/i_17.ct
Homomorphic execution...
Total execution time 3.39207 seconds
READ time 0.00457964 seconds, #execs 16
COPY time 0.0103953 seconds, #execs 109
XOR gates execution time 0.00135947 seconds, #execs 11
NOT gates execution time 0.000814061 seconds, #execs 26
AND gates execution time 1.86519 seconds, #execs 40
OR gates execution time 1.4953 seconds, #execs 32
WRITE time 0.00249801 seconds, #execs 8
Maximal number of simultaneously allocated ciphertexts 21
3.39user 0.00system 0:03.40elapsed 99%CPU (0avgtext+0avgdata 30480maxresident)k
1320inputs+3008outputs (4major+7107minor)pagefaults 0swaps
Output decryption
38 

It is not a surprise: the result of 20 and 18 is 38!

For more complicated examples of applications using Cingulata, go to the tests/ directory.

We hope that you have found this tutorial helpful! If you have any issues or suggestions, please drop us a note on how we can improve !

Enjoy your walk through Cingulata world!

Clone this wiki locally