Python Developer Quickstart
Start building on Nillion. The quickstart walks you through
- Installing the Nillion SDK
- Setting up a developer environment
- Running and connecting to nillion-devnet, a local Nillion network
- Writing your first Nada program,
tiny_secret_addition.py
- Connecting to the network with the NillionClient to store programs, store secrets, and compute on programs with stored secrets.
Install the Nillion SDK tools
-
Install nilup the Nillion SDK tool installer and version manager. Binaries are available for Linux and macOS platforms
For the security-conscious, please download the
install.sh
script, so that you can inspect how it works, before piping it tobash
.curl https://nilup.nilogy.xyz/install.sh | bash
Confirm global
nilup
tool installationnilup -V
-
Use nilup to install the latest version of the Nillion SDK.
nilup install latest
nilup use latest
nilup initOptionally enable
nilup
telemetry, providing your Ethereum wallet address. We collect this data to understand how the software is used, and to better assist you in case of issues.In doing this, you consent to the collection of telemetry data by the Nillion Network. While we will not collect any personal information, we still recommend using a new wallet address that cannot be linked to your identity by any third party. For more information, check out our privacy policy.nilup instrumentation enable --wallet <your-eth-wallet-address>
Confirm global Nillion tool installation
nillion -V
Clone the Nillion python starter repo
The Nillion Python Starter repo has everything you need to start building. Clone the repo:
git clone https://github.com/NillionNetwork/nillion-python-starter.git
cd nillion-python-starter
Install script dependencies
There are a few pre-reqs for using the python starter repo: make sure you have python3 (version >=3.11) and pip, foundry, pidof, and grep installed on your machine.
-
python3 version >=3.11 version 3.11 or higher with a working pip installed
tipUse these commands to confirm that you have python3 (version >=3.11) and pip installed:
python3 --version
python3 -m pip --version -
anvil tool from foundry, which can be installed with:
# install Foundryup, the Foundry toolchain installer
curl -L https://foundry.paradigm.xyz | bash
# after installation, use the foundryup commmand to install the binaries including Anvil
foundryup
Create a .env file by copying the sample
cp .env.sample .env
Activate the virtual environment
These scripts activate a python virtual environment at .venv and install py_nillion_client and nada_dsl packages + dependencies listed in the requirements.txt
file
bash ./create_venv.sh && source .venv/bin/activate
Bootstrap your local environment and run the nillion-devnet
The bootstrap-local-environment script installs Nada DSL and Nillion Client, then uses the nillion-devnet Nillion SDK tool to spin up a local test Nillion cluster that is completely isolated within your computer. The script also populates your .env file with keys, bootnodes, cluster, and payment info that will allow you to connect to the local cluster network.
./bootstrap-local-environment.sh
You can stop the local cluster at any time by running
killall nillion-devnet
Write a Nada program
The Nillion Network uses Nada, our MPC language, to define MPC programs. The first implementation of Nada is a Python DSL (Domain Specific Language), called Nada. Let's write a tiny Nada program that adds two secret numbers. Here's the code for the finished program we'll write line by line:
loading...
Create a python file called tiny_secret_addition.py
in the programs folder. This is where you will write your Nada program code.
cd programs
touch tiny_secret_addition.py
Open the file and import nada_dsl
from nada_dsl import *
Create a function called nada_main() that will contain the code you want to run
from nada_dsl import *
def nada_main():
Add a party
In Nada you have to declare the parties involved in the computation through the Party
type. A Party
is defined with a name.
Here's an example of a Party
Party(name="Steph")
Create party1, a Party
named "Party1"
from nada_dsl import *
def nada_main():
party1 = Party(name="Party1")
Learn about inputs
Nada programs have inputs. An Input
is defined with a name and a party, which is the Party
providing the input.
Here's an example of an Input
:
Input(name="numberOfDogs", party=Party(name="Steph"))
Nada program inputs are typed. There are a few categories of types
Secrecy level
- Public: visible to all nodes
- Secret: secret values to be handled by the computing nodes as shares or particles
Scalar
- Integer
- String
These categories are combined into types like SecretInteger
, which are used to type an Input. See all types
Here's an example of a SecretInteger
Input provided by Steph
steph = Party(name="Steph")
stephs_secret_int = SecretInteger(Input(name="numberOfDogs", party=steph))
Create 2 secret integers inputs
my_int1
, aSecretInteger
named "my_int1" owned by Party1my_int2
, aSecretInteger
named "my_int2" owned by Party1
from nada_dsl import *
def nada_main():
party1 = Party(name="Party1")
my_int1 = SecretInteger(Input(name="my_int1", party=party1))
my_int2 = SecretInteger(Input(name="my_int2", party=party1))
Add the integers by creating a new variable called new_int and setting it equal to my_int1 + my_int2
from nada_dsl import *
def nada_main():
party1 = Party(name="Party1")
my_int1 = SecretInteger(Input(name="my_int1", party=party1))
my_int2 = SecretInteger(Input(name="my_int2", party=party1))
new_int = my_int1 + my_int2
Finally, Nada programs return an output. The Output
type is used to declare a named output that will be revealed to a concrete Party
. The Output has a name and a party as parameters.
Return the output
Nada programs return an array of outputs.
Here's an example of an output. The output is named total_score
, its value is score_int
, and it can be read by the party named Steph.
Output(score_int, "total_score", Party(name="Steph"))
Complete your Nada program by adding a final line that returns an array with one output. The output is named "my_output", its value is new_int
, and it can be ready by party1
.
Resulting Nada program
loading...
🎉 You just wrote your first Nada program! Next, let's compile the program.
Compile the Nada program
Nada programs need to be compiled ahead of being stored. Navigate back to the root of the repo, and compile all programs in the programs folder, including tiny_secret_addition.py, with the compile script. The compile_programs.sh script runs the pynadac SDK tool on all files in the programs folder.
cd ..
sh compile_programs.sh
This results in programs-compiled, a folder of compiled programs. Check programs-compiled for your compiled output, called tiny_secret_addition.nada.bin
Write a Python script to interact with nillion-devnet
Let's write a Python script that will interact with nillion-devnet. This Python script will:
- Initialize NillionClient, connecting to nillion-devnet
- Get the user id and party id from NillionClient
- Store a compiled Nada program in the network
- Create the 1st secret with bindings to the program
- Store the secret in the network
- Create compute bindings to set input and output parties
- Compute on the program with 1st secret from the network, and the 2nd secret, provided at compute time
- Print the computation result
Check out the completed Python script here
Complete the python script 🎯 TODOs
Open the core_concept_single_party_compute/tiny_secret_addition.py file and let's work through the 🎯 TODOs.
Open the Nillion Python Client Reference doc in another tab to search for available classes while completing the 🎯 TODOs.
1. Initialize NillionClient, connecting to nillion-devnet
The first step was completed for you. The script uses a create_nillion_client
helper file to create the instance of nillion.NillionClient
used throughout the script
- Todo #1
- Complete #1
- create_nillion_client helper
loading...
loading...
loading...
2. Get the user id and party id from NillionClient
- Todo #2
- Complete #2
loading...
loading...
3. Store a compiled Nada program in the network
- Todo #3
- Complete #3
loading...
loading...
4. Create the 1st secret with bindings to the program
- Todo #4
- Complete #4
loading...
loading...
5. Store the secret in the network
When we wrote our Nada program, we created 2 secret integers that are inputs to the program. We'll store one of these secrets in the network using the Python Client, and provide the other secret at compute time. Let's store the first secret.
- Todo #5
- Complete #5
loading...
loading...
6. Create compute bindings to set input and output parties
- Todo #6
- Complete #6
loading...
loading...
7. Compute on the program with 1st secret from the network, and the 2nd secret, provided at compute time
- Todo #7
- Complete #7
loading...
loading...
8. Print the computation result
- Todo #8
- Complete #8
loading...
loading...
Run the completed python script
Run the script to store the program, store secrets and compute on the program.
cd core_concept_single_party_compute
python3 tiny_secret_addition.py
Check out the network result on tiny_secret_addition. Update the SecretInteger input values and run the program again.
Keep exploring
You've successfully written your first single party Nada program, stored the program on the network, stored secrets on the network, and run compute against secrets. Keep exploring by
-
running other examples
- single party program examples in the core_concept_single_party_compute folder
- multi party examples in the core_concept_multi_party_compute folder
- permissioning secrets examples in the in the permissions folder for storing and retrieving permissioned secrets and revoking permissions
-
reading about Nillion concepts and the Nada Language
-
learning how to interact with and manage programs, secrets, and permissions on the Nillion Network with Nillion Client
-
solving the millionaires problem in the millionaires_problem_example folder