-
Notifications
You must be signed in to change notification settings - Fork 565
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #31 from NillionNetwork/colab_starter_changes
Colab starter changes
- Loading branch information
Showing
4 changed files
with
284 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
#!/usr/bin/env bash | ||
|
||
# set number of node and user keys to be created | ||
num_node_keys=5 | ||
num_user_keys=5 | ||
|
||
# set env file to update | ||
ENV_TO_UPDATE=".env" | ||
|
||
NILLION_DEVNET="/root/.nilup/sdks/latest/nillion-devnet" | ||
NILLION_CLI="/root/.nilup/sdks/latest/nillion" | ||
NILLION_CLI_COMMAND_USER_KEYGEN="user-key-gen" | ||
NILLION_CLI_COMMAND_NODE_KEYGEN="node-key-gen" | ||
|
||
# kill any other nillion-devnet processes | ||
pkill -9 -f $NILLION_DEVNET | ||
|
||
for var in NILLION_DEVNET NILLION_CLI; do | ||
printf "ℹ️ found bin %-18s -> [${!var:?Failed to discover $var}]\n" "$var" | ||
done | ||
|
||
OUTFILE=$(mktemp); | ||
PIDFILE=$(mktemp); | ||
|
||
"$NILLION_DEVNET" >"$OUTFILE" & echo $! >"$PIDFILE"; | ||
echo "--------------------" | ||
echo "Updating your ${ENV_TO_UPDATE} files with nillion-devnet environment info... This may take a minute." | ||
echo "--------------------" | ||
time_limit=160 | ||
while true; do | ||
# Use 'wait' to check if the log file contains the string | ||
if grep "cluster is running, bootnode is at" "$OUTFILE"; then | ||
break | ||
fi | ||
|
||
# If the time limit has been reached, print an error message and exit | ||
if [[ $SECONDS -ge $time_limit ]]; then | ||
echo "Timeout reached while waiting for cluster to be ready in '$OUTFILE'" >&2 | ||
exit 1 | ||
fi | ||
sleep 5 | ||
done | ||
|
||
echo "ℹ️ Cluster has been STARTED (see $OUTFILE)" | ||
cat "$OUTFILE" | ||
|
||
# grep cluster info from nillion-devnet | ||
CLUSTER_ID=$(grep "cluster id is" "$OUTFILE" | awk '{print $4}'); | ||
WEBSOCKET=$(grep "websocket:" "$OUTFILE" | awk '{print $2}'); | ||
BOOT_MULTIADDR=$(grep "cluster is running, bootnode is at" "$OUTFILE" | awk '{print $7}'); | ||
PAYMENTS_CONFIG_FILE=$(grep "payments configuration written to" "$OUTFILE" | awk '{print $5}'); | ||
WALLET_KEYS_FILE=$(grep "wallet keys written to" "$OUTFILE" | awk '{print $5}'); | ||
PAYMENTS_RPC=$(grep "blockchain_rpc_endpoint:" "$PAYMENTS_CONFIG_FILE" | awk '{print $2}'); | ||
PAYMENTS_CHAIN=$(grep "chain_id:" "$PAYMENTS_CONFIG_FILE" | awk '{print $2}'); | ||
PAYMENTS_SC_ADDR=$(grep "payments_sc_address:" "$PAYMENTS_CONFIG_FILE" | awk '{print $2}'); | ||
PAYMENTS_BF_ADDR=$(grep "blinding_factors_manager_sc_address:" "$PAYMENTS_CONFIG_FILE" | awk '{print $2}'); | ||
WALLET_PRIVATE_KEY=$(tail -n1 "$WALLET_KEYS_FILE") | ||
|
||
# update or add an environment variable to one or more files | ||
update_env() { | ||
local key=$1 | ||
local value=$2 | ||
# Skip the first two arguments to get the file paths | ||
local files=("${@:3}") | ||
|
||
for file in "${files[@]}"; do | ||
if [ -f "$file" ]; then # Check if file exists | ||
# Check if the key exists in the file and remove it | ||
if grep -q "^$key=" "$file"; then | ||
# Key exists, remove it | ||
grep -v "^$key=" "$file" > temp.txt && mv temp.txt "$file" | ||
fi | ||
|
||
# Append the new key-value pair to the file | ||
echo "$key=$value" >> "$file" | ||
else | ||
echo "File $file not found. Creating $file" | ||
touch $file | ||
echo "$key=$value" >> "$file" | ||
fi | ||
done | ||
} | ||
|
||
# log file contents of key files to add to .env | ||
log_file_contents() { | ||
local file_path=$1 # Direct path to the target file | ||
|
||
# Check if the file exists at the path | ||
if [[ ! -f "$file_path" ]]; then | ||
echo "File $file_path does not exist." | ||
return 1 # Exit the function with an error status if the file does not exist | ||
fi | ||
|
||
# If the file exists, cat its contents | ||
cat "$file_path" | ||
} | ||
|
||
# Generate node keys and add to .env - ex: NILLION_NODEKEY_PATH_PARTY_1 | ||
for ((i=1; i<=$num_node_keys; i++)); do | ||
nodekey_file=$(mktemp) | ||
"$NILLION_CLI" "$NILLION_CLI_COMMAND_NODE_KEYGEN" "$nodekey_file" | ||
NODEKEY_FILES+=("$nodekey_file") | ||
update_env "NILLION_NODEKEY_PATH_PARTY_$i" "$nodekey_file" $ENV_TO_UPDATE | ||
update_env "NILLION_NODEKEY_TEXT_PARTY_$i" "$(log_file_contents $nodekey_file)" $ENV_TO_UPDATE | ||
done | ||
|
||
# Generate user keys and add to .env - ex: NILLION_USERKEY_PATH_PARTY_1 | ||
for ((i=1; i<=$num_user_keys; i++)); do | ||
userkey_file=$(mktemp) | ||
"$NILLION_CLI" "$NILLION_CLI_COMMAND_USER_KEYGEN" "$userkey_file" | ||
USERKEY_FILES+=("$userkey_file") | ||
update_env "NILLION_USERKEY_PATH_PARTY_$i" "$userkey_file" $ENV_TO_UPDATE | ||
update_env "NILLION_USERKEY_TEXT_PARTY_$i" "$(log_file_contents $userkey_file)" $ENV_TO_UPDATE | ||
done | ||
|
||
echo "🔑 Node key and user keys have been generated and added to .env" | ||
|
||
# Add environment variables to .env | ||
update_env "NILLION_WEBSOCKETS" "$WEBSOCKET" $ENV_TO_UPDATE | ||
update_env "NILLION_CLUSTER_ID" "$CLUSTER_ID" $ENV_TO_UPDATE | ||
update_env "NILLION_BLOCKCHAIN_RPC_ENDPOINT" "$PAYMENTS_RPC" $ENV_TO_UPDATE | ||
update_env "NILLION_BLINDING_FACTORS_MANAGER_SC_ADDRESS" "$PAYMENTS_BF_ADDR" $ENV_TO_UPDATE | ||
update_env "NILLION_PAYMENTS_SC_ADDRESS" "$PAYMENTS_SC_ADDR" $ENV_TO_UPDATE | ||
update_env "NILLION_CHAIN_ID" "$PAYMENTS_CHAIN" $ENV_TO_UPDATE | ||
update_env "NILLION_WALLET_PRIVATE_KEY" "$WALLET_PRIVATE_KEY" $ENV_TO_UPDATE | ||
update_env "NILLION_BOOTNODE_MULTIADDRESS" "$BOOT_MULTIADDR" $ENV_TO_UPDATE | ||
|
||
echo "Running at process pid: $(pgrep -f $NILLION_DEVNET)" | ||
|
||
echo "-------------------------------------------------------" | ||
echo " 7MM 7MM " | ||
echo " MM MM " | ||
echo " db MM MM db " | ||
echo " MM MM " | ||
echo ".7MMpMMMb. 7MM MM MM 7MM ,pW-Wq. 7MMpMMMb. " | ||
echo " MM MM MM MM MM MM 6W' Wb MM MM " | ||
echo " MM MM MM MM MM MM 8M M8 MM MM " | ||
echo " MM MM MM MM MM MM YA. ,A9 MM MM " | ||
echo ".JMML JMML..JMML..JMML..JMML..JMML. Ybmd9 .JMML JMML." | ||
echo "-------------------------------------------------------" | ||
echo "-------------------------------------------------------" | ||
echo "-----------🦆 CONNECTED TO NILLION-DEVNET 🦆-----------" | ||
echo "-------------------------------------------------------" | ||
|
||
echo "ℹ️ Your $ENV_TO_UPDATE file configurations were updated with nillion-devnet connection variables: websocket, cluster id, keys, blockchain info" | ||
echo "💻 The Nillion devnet is still running behind the scenes; to spin down the Nillion devnet at any time, run 'killall nillion-devnet'" | ||
|
||
echo "--------------------" | ||
echo "💻 Your Nillion local cluster is still running - process pid: $(pgrep -f $NILLION_DEVNET)" | ||
echo "ℹ️ Updated your .env file configuration variables: bootnode, cluster id, keys, blockchain info" | ||
|
||
exit 0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
#!/usr/bin/env bash | ||
|
||
# This script compiles all $PROGRAMS_FOLDER programs to mir | ||
PROGRAMS_FOLDER="programs" | ||
COMPILED_PROGRAMS_FOLDER="programs-compiled" | ||
|
||
SCRIPT_PATH="$(cd "$(dirname "${BASH_SOURCE[0]}" 2>/dev/null)" && pwd -P)" | ||
TARGET_PATH="${SCRIPT_PATH}/${COMPILED_PROGRAMS_FOLDER}" | ||
PROGRAMS_PATH="${SCRIPT_PATH}/${PROGRAMS_FOLDER}" | ||
|
||
PYNADAC="/root/.nilup/sdks/latest/pynadac" | ||
|
||
cd "${PROGRAMS_PATH}" || exit 1 | ||
|
||
for file in *.py ; do | ||
echo "Compiling ${file}" | ||
"$PYNADAC" --target-dir "${TARGET_PATH}" \ | ||
--generate-mir-json \ | ||
"${file}" | ||
done | ||
|
||
echo "------------------------" | ||
echo "Compiled programs: all files in the programs directory were compiled to mir: [$TARGET_PATH]" | ||
|
||
echo "Now try running an example:" | ||
|
||
echo "----------single party compute --------------" | ||
|
||
echo "Code for single party compute lives in the examples_and_tutorials/core_concept_client_single_party_compute folder" | ||
echo "📋 to run single party compute - addition_simple program: 'cd examples_and_tutorials/core_concept_client_single_party_compute && python3 addition_simple.py'" | ||
|
||
echo "----------multi party compute --------------" | ||
|
||
echo "Code for multi party compute lives in the examples_and_tutorials/core_concept_multi_party_compute folder" | ||
echo "📋 to run multi party compute in 3 steps - addition_simple_multi_party_3: 'cd examples_and_tutorials/core_concept_multi_party_compute && python3 01_store_secret_party1.py'" |
85 changes: 85 additions & 0 deletions
85
examples_and_tutorials/core_concept_single_party_compute/my_first_program.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
import asyncio | ||
import py_nillion_client as nillion | ||
import os | ||
import sys | ||
import pytest | ||
|
||
from dotenv import load_dotenv | ||
|
||
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../..'))) | ||
from helpers.nillion_client_helper import create_nillion_client | ||
from helpers.nillion_keypath_helper import getUserKeyFromFile, getNodeKeyFromFile | ||
|
||
load_dotenv() | ||
|
||
|
||
# 1 Party running your first program on 1 stored secret and 1 compute time secret | ||
async def main(): | ||
cluster_id = os.getenv("NILLION_CLUSTER_ID") | ||
userkey = getUserKeyFromFile(os.getenv("NILLION_USERKEY_PATH_PARTY_1")) | ||
nodekey = getNodeKeyFromFile(os.getenv("NILLION_NODEKEY_PATH_PARTY_1")) | ||
client = create_nillion_client(userkey, nodekey) | ||
party_id = client.party_id | ||
user_id = client.user_id | ||
party_name = "Party1" | ||
program_name = "my_first_program" | ||
program_mir_path = f"../../programs-compiled/{program_name}.nada.bin" | ||
|
||
# store program | ||
action_id = await client.store_program( | ||
cluster_id, program_name, program_mir_path | ||
) | ||
|
||
program_id = f"{user_id}/{program_name}" | ||
print('Stored program. action_id:', action_id) | ||
print('Stored program_id:', program_id) | ||
|
||
# Create a secret | ||
stored_secret = nillion.Secrets({ | ||
"my_int1": nillion.SecretInteger(500), | ||
}) | ||
secret_bindings = nillion.ProgramBindings(program_id) | ||
secret_bindings.add_input_party(party_name, party_id) | ||
|
||
# Store a secret | ||
store_id = await client.store_secrets( | ||
cluster_id, secret_bindings, stored_secret, None | ||
) | ||
|
||
# Bind the parties in the computation to the client to set input and output parties | ||
compute_bindings = nillion.ProgramBindings(program_id) | ||
compute_bindings.add_input_party(party_name, party_id) | ||
compute_bindings.add_output_party(party_name, party_id) | ||
|
||
print(f"Computing using program {program_id}") | ||
print(f"Use secret store_id: {store_id}") | ||
|
||
computation_time_secrets = nillion.Secrets({"my_int2": nillion.SecretInteger(10)}) | ||
|
||
# Compute on the secret | ||
compute_id = await client.compute( | ||
cluster_id, | ||
compute_bindings, | ||
[store_id], | ||
computation_time_secrets, | ||
nillion.PublicVariables({}), | ||
) | ||
|
||
# Print compute result | ||
print(f"The computation was sent to the network. compute_id: {compute_id}") | ||
while True: | ||
compute_event = await client.next_compute_event() | ||
if isinstance(compute_event, nillion.ComputeFinishedEvent): | ||
print(f"✅ Compute complete for compute_id {compute_event.uuid}") | ||
print(f"🖥️ The result is {compute_event.result.value}") | ||
return compute_event.result.value | ||
|
||
|
||
if __name__ == "__main__": | ||
asyncio.run(main()) | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_main(): | ||
result = await main() | ||
assert result == {'my_output': 510} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
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)) | ||
|
||
# write the computation for your program here - use my_int1 and my_int2 as inputs | ||
# make sure you change the output below to be your new output | ||
|
||
return [Output(my_int1, "my_output", party1)] |