After developing your circuit, you may want to deploy it. However, sharing the details of your circuit with every client might not be desirable. You might want to perform the computation in dedicated servers, as well. In this case, you can use the
Serverfeatures of Concrete.
You can develop your circuit like we've discussed in the previous chapters. Here is a simple example:
from concrete import fhe
return x + 42
inputset = range(10)
circuit = function.compile(inputset)
Once you have your circuit, you can save everything the server needs:
server.zipto your computation server.
You can load the
server.zipyou get from the development machine:
from concrete import fhe
server = fhe.Server.load("server.zip")
You will need to wait for requests from clients. The first likely request is for
ClientSpecsto generate keys and request computation. You can serialize
serialized_client_specs: str = server.client_specs.serialize()
Then, you can send it to the clients requesting it.
After getting the serialized
ClientSpecsfrom a server, you can create the client object:
client_specs = fhe.ClientSpecs.deserialize(serialized_client_specs)
client = fhe.Client(client_specs)
Once you have the
Clientobject, you can perform key generation:
This method generates encryption/decryption keys and evaluation keys.
The server requires evaluation keys linked to the encryption keys that you just generated. You can serialize your evaluation keys as shown:
serialized_evaluation_keys: bytes = client.evaluation_keys.serialize()
After serialization, send the evaluation keys to the server.
Serialized evaluation keys are very big in size, so you may want to cache them on the server instead of sending them with each request.
Now encrypt your inputs and request the server to perform the computation. You can do it like so:
serialized_args: bytes = client.encrypt(7).serialize()
Then, send serialized args to the server.
Once you have serialized evaluation keys and serialized arguments, you can deserialize them:
deserialized_evaluation_keys = fhe.EvaluationKeys.deserialize(serialized_evaluation_keys)
deserialized_args = server.client_specs.deserialize_public_args(serialized_args)
You can perform the computation, as well:
public_result = server.run(deserialized_args, deserialized_evaluation_keys)
serialized_public_result: bytes = public_result.serialize()
Then, send the serialized public result back to the client, so they can decrypt it and get the result of the computation.
Once you have received the public result of the computation from the server, you can deserialize it:
deserialized_public_result = client.specs.deserialize_public_result(serialized_public_result)
Then, decrypt the result:
result = client.decrypt(deserialized_public_result)
assert result == 49