Prover/Verifier Integration
It is very easy to develop or modify a prover or verifier to run in Gevulot. Almost any program that can be compiled as an ELF binary for the Linux x86_64 architecture works, but in order to integrate the program with Gevulot and for it to be able to handle received workloads, it needs to work with the specified gRPC protocol.
Running environment
The program running environment in a Nanos unikernel is very similar to a normal Linux system, but it does include the following restrictions that originate from either Nanos or Gevulot:
Not all syscalls are supported. See list of Nanos supported syscalls.
There is no networking for security reasons. In on-prem environment there is not even a NIC. In cloud environment there is strictly restricted networking between a Gevulot node and the program VM instance (for gRPC connection only).
No fork() support. The whole running environment is single-process only. Multiple threads are supported normally.
Root filesystem is read-only. Read-write enabled ephemeral volume is mounted in /workspace. This is replaced after every Task execution.
Shim
To ease the running of existing programs in Gevulot, there is a helper library called shim that provides some simple functionality to integrate the program with Gevulot.
Shim is written in Rust, but it has C FFI bindings to use in programs written in C/C++ or to allow creation of bindings to other programming languages.
Rust
Needed changes for existing programs
To modify an existing program for use in Gevulot using the shim library, the following changes are needed:
1. Provide callback function for running a task
Provide callback function for running a task. This could be e.g. a slightly modified existing main() function that parses program arguments from Task.args instead of std::env::args(). The signature for the callback function is the following:
2. Create a new main()
Replace the old main() function with a new one that delegates control to shim:
Complete example
This is a complete example program in Rust, that can be run inside Gevulot.
C/C++
Gevulot shim
Since gevulot-shim itself is written in Rust, there is a separate gevulot-shim-ffi crate that provides C-bindings via FFI.
Compile the FFI crate to get libgevulot_shim_ffi.so that is then linked into the program binary.
Needed changes for existing programs
C/C++ programs are nearly identical with Rust programs regarding the changes needed for existing programs. There are a couple of small differences in the program flow due to differences in memory management.
1. Include the header file for FFI bindings
shim.h provides function definitions for gevulot-shim-ffi.
Shim header is a C header file. If it is included from C++ program, it must be wrapped with extern
as follows:
2. Provide callback function for running a task
Provide callback function for running a task. This could be e.g. a slightly modified existing main() function that parses program arguments from Task->args instead of **argv. The signature for the callback function is the following:
Here the return value of void* denotes the TaskResult struct that is fully managed by the shim library.
3. Create a new main()
Replace the old main() function with a new one that delegates the control to shim:
Complete example
This is a complete example program in C, that can be run inside Gevulot.
Differences to Rust shim
Due to memory management there are a couple of differences to the Rust version in gevulot-shim-ffi C/C++ interface:
TaskResult object is created with new_task_result(data, len) function.
Files that are communicated back to Gevulot node, are added with add_file_to_result(task_result, file_name) function.
Last updated