From 614ca64b726e43975ecfc2bf0d05cd5958310c88 Mon Sep 17 00:00:00 2001 From: aeesh Date: Thu, 24 Oct 2024 19:20:24 +0200 Subject: [PATCH 1/2] draft --- services/e2e.ipynb | 635 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 635 insertions(+) create mode 100644 services/e2e.ipynb diff --git a/services/e2e.ipynb b/services/e2e.ipynb new file mode 100644 index 0000000..1c47c62 --- /dev/null +++ b/services/e2e.ipynb @@ -0,0 +1,635 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "JaUba7vsukRz" + }, + "source": [ + "This workbook represent an end to end test of the Nillion network. It will test the following:\n", + "1. A user (patient) uploading their data in encrypted form and providing access to Monadic\n", + "2. Monadic giving compute access to Snipper, a third party\n", + "3. Snipper registering a program and running in on the patient's encrypted data\n", + "\n", + "Before running this workbook, ensure Nillion Devnet is running. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Install all Python prerequisites. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "ExecuteTime": { + "end_time": "2024-08-09T19:26:51.222994Z", + "start_time": "2024-08-09T19:26:43.883908Z" + }, + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "JAGtpt87u119", + "outputId": "2d8deba3-069f-4449-df93-f58ba31841f5" + }, + "outputs": [], + "source": [ + "%pip install nada-dsl==0.6.0\n", + "%pip install py-nillion-client==0.6.0\n", + "%pip install nillion-python-helpers==0.2.3\n", + "%pip install python-dotenv==1.0.0\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Import all necessary libraries" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "ExecuteTime": { + "end_time": "2024-08-09T23:28:05.762189Z", + "start_time": "2024-08-09T23:28:05.723159Z" + }, + "id": "EQCfD717Sb-M" + }, + "outputs": [], + "source": [ + "import py_nillion_client as nillion\n", + "from py_nillion_client import NodeKey, UserKey\n", + "from dotenv import load_dotenv\n", + "from nillion_python_helpers import get_quote_and_pay, create_nillion_client, create_payments_config\n", + "from cosmpy.aerial.client import LedgerClient\n", + "from cosmpy.aerial.wallet import LocalWallet\n", + "from cosmpy.crypto.keypairs import PrivateKey" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Load the environment variables from a Devnet .env file\n", + "\n", + "*Please make sure to replace the path with the correct path to your .env file*" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "ExecuteTime": { + "end_time": "2024-08-09T23:28:08.870617Z", + "start_time": "2024-08-09T23:28:08.850035Z" + }, + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "XWsJmklOEeh1", + "outputId": "fff3de58-4f50-4e09-99f9-d7b6cdb943ed" + }, + "outputs": [], + "source": [ + "import os\n", + "\n", + "home_dir = os.path.expanduser(\"~\")\n", + "env_path = os.path.join(home_dir, \".config\", \"nillion\", \"nillion-devnet.env\")\n", + "\n", + "print(f\"Loading environment variables from {env_path}\")\n", + "\n", + "load_dotenv(env_path)\n", + "\n", + "for key, value in os.environ.items():\n", + " if key.startswith(\"NILLION_\"):\n", + " print(f\"{key}: {value}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Read in some basic Nillion network information from the environment. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "ExecuteTime": { + "end_time": "2024-08-09T23:28:12.833625Z", + "start_time": "2024-08-09T23:28:12.815576Z" + } + }, + "outputs": [], + "source": [ + "cluster_id = os.getenv('NILLION_CLUSTER_ID')\n", + "chain_id = os.getenv('NILLION_NILCHAIN_CHAIN_ID')\n", + "grpc_endpoint = os.getenv('NILLION_NILCHAIN_GRPC')\n", + "\n", + "print(f\"Cluster ID: {cluster_id}\")\n", + "print(f\"Chain ID: {chain_id}\")\n", + "print(f\"GRPC Endpoint: {grpc_endpoint}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Each actor will need its own node key so we define a utility function here." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "ExecuteTime": { + "end_time": "2024-08-09T23:28:16.326786Z", + "start_time": "2024-08-09T23:28:16.320243Z" + } + }, + "outputs": [], + "source": [ + "import uuid\n", + "def gen_node_key():\n", + " return NodeKey.from_seed(uuid.uuid4().hex)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Setup for the Monadic actor" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "ExecuteTime": { + "end_time": "2024-08-09T23:28:19.828183Z", + "start_time": "2024-08-09T23:28:19.615786Z" + } + }, + "outputs": [], + "source": [ + "monadic_seed = \"monadic_seed\"\n", + "monadic_userkey = UserKey.from_seed(monadic_seed)\n", + "monadic_client = create_nillion_client(monadic_userkey, gen_node_key())\n", + "monadic_party_id = monadic_client.party_id\n", + "monadic_user_id = monadic_client.user_id" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Setup for the Snipper actor" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "ExecuteTime": { + "end_time": "2024-08-09T23:28:22.512975Z", + "start_time": "2024-08-09T23:28:22.489237Z" + } + }, + "outputs": [], + "source": [ + "snipper_seed = \"snipper_seed\"\n", + "snipper_userkey = UserKey.from_seed(snipper_seed)\n", + "snipper_client = create_nillion_client(snipper_userkey, gen_node_key())\n", + "snipper_party_id = snipper_client.party_id\n", + "snipper_user_id = snipper_client.user_id" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Setup for the Patient actor" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "ExecuteTime": { + "end_time": "2024-08-09T23:28:28.760101Z", + "start_time": "2024-08-09T23:28:28.734404Z" + } + }, + "outputs": [], + "source": [ + "patient_seed = \"patient_seed\"\n", + "patient_userkey = UserKey.from_seed(patient_seed)\n", + "patient_client = create_nillion_client(patient_userkey, gen_node_key())\n", + "patient_party_id = patient_client.party_id\n", + "patient_user_id = patient_client.user_id" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Payments set up for all network actions" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "ExecuteTime": { + "end_time": "2024-08-09T23:28:31.282228Z", + "start_time": "2024-08-09T23:28:31.238065Z" + }, + "id": "pkaCYaErQ8kf" + }, + "outputs": [], + "source": [ + "payments_config = create_payments_config(chain_id, grpc_endpoint)\n", + "payments_client = LedgerClient(payments_config)\n", + "payments_wallet = LocalWallet(\n", + " PrivateKey(bytes.fromhex(os.getenv(\"NILLION_NILCHAIN_PRIVATE_KEY_0\"))),\n", + " prefix=\"nillion\",\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Configuration for the program to use. Change the contents of the below cell to use another program. " + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "ExecuteTime": { + "end_time": "2024-08-09T23:28:33.143041Z", + "start_time": "2024-08-09T23:28:33.134076Z" + }, + "id": "rEr0_JkMuVci" + }, + "outputs": [], + "source": [ + "program_name = \"double\"\n", + "program_mir_path = f\"binaries/double.nada.bin\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As a baseline, let's ensure that the user can store the program and run it on their own secret. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "ExecuteTime": { + "end_time": "2024-08-09T23:28:41.524938Z", + "start_time": "2024-08-09T23:28:35.164639Z" + } + }, + "outputs": [], + "source": [ + "import os\n", + "\n", + "os.environ['RUST_BACKTRACE'] = '1'\n", + "\n", + "print(\"The patient is storing the program on the network\")\n", + "\n", + "async def store_program():\n", + " receipt_store_program = await get_quote_and_pay(\n", + " patient_client,\n", + " nillion.Operation.store_program(program_mir_path),\n", + " payments_wallet,\n", + " payments_client,\n", + " cluster_id,\n", + " )\n", + "\n", + " # Store the program\n", + " action_id = await patient_client.store_program(\n", + " cluster_id, program_name, program_mir_path, receipt_store_program\n", + " )\n", + " return action_id\n", + "\n", + "action_id = await store_program()\n", + "print(f\"Action ID: {action_id}\")\n", + "\n", + "print(\"The patient is storing a secret on the network\")\n", + "\n", + "program_id = f\"{patient_user_id}/{program_name}\"\n", + "\n", + "new_secret = nillion.NadaValues(\n", + " {\n", + " \"foo\": nillion.SecretInteger(2),\n", + " }\n", + ")\n", + "\n", + "# Set permissions for the client to compute on the program\n", + "permissions = nillion.Permissions.default_for_user(patient_user_id)\n", + "permissions.add_compute_permissions({patient_user_id: {program_id}})\n", + "\n", + "# Pay for and store the secret in the network and print the returned store_id\n", + "receipt_store = await get_quote_and_pay(\n", + " patient_client,\n", + " nillion.Operation.store_values(new_secret, ttl_days=5),\n", + " payments_wallet,\n", + " payments_client,\n", + " cluster_id,\n", + ")\n", + "# Store a secret\n", + "store_id = await patient_client.store_values(\n", + " cluster_id, new_secret, permissions, receipt_store\n", + ")\n", + "\n", + "print(\"The patient is running the program on the secret..\")\n", + "\n", + "party_name = \"Party1\"\n", + "compute_bindings = nillion.ProgramBindings(program_id)\n", + "compute_bindings.add_input_party(party_name, patient_party_id)\n", + "compute_bindings.add_output_party(party_name, patient_party_id)\n", + "computation_time_secrets = nillion.NadaValues({})\n", + "\n", + "# Pay for the compute\n", + "receipt_compute = await get_quote_and_pay(\n", + " patient_client,\n", + " nillion.Operation.compute(program_id, computation_time_secrets),\n", + " payments_wallet,\n", + " payments_client,\n", + " cluster_id,\n", + ")\n", + "\n", + "# Compute on the secret\n", + "compute_id = await patient_client.compute(\n", + " cluster_id,\n", + " compute_bindings,\n", + " [store_id],\n", + " computation_time_secrets,\n", + " receipt_compute,\n", + ")\n", + "\n", + "# 8. Return the computation result\n", + "print(f\"The computation was sent to the network. compute_id: {compute_id}\")\n", + "while True:\n", + " compute_event = await patient_client.next_compute_event()\n", + " if isinstance(compute_event, nillion.ComputeFinishedEvent):\n", + " print(f\"✅ Compute complete for compute_id {compute_event.uuid}\")\n", + " print(f\"🖥️ The result is {compute_event.result.value}\")\n", + " break" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Have Monadic store the program on the network\n", + "\n", + "TODO: Also have Snipper save the program and replicate the computation" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "ExecuteTime": { + "end_time": "2024-08-09T23:28:49.395066Z", + "start_time": "2024-08-09T23:28:47.351151Z" + }, + "colab": { + "base_uri": "https://localhost:8080/", + "height": 211 + }, + "id": "wgS0N715Qid2", + "outputId": "eb833ff1-b29c-492b-b3c4-271a08a86b51" + }, + "outputs": [], + "source": [ + "async def store_program():\n", + " receipt_store_program = await get_quote_and_pay(\n", + " monadic_client,\n", + " nillion.Operation.store_program(program_mir_path),\n", + " payments_wallet,\n", + " payments_client,\n", + " cluster_id,\n", + " )\n", + "\n", + " # Store the program\n", + " action_id = await monadic_client.store_program(\n", + " cluster_id, program_name, program_mir_path, receipt_store_program\n", + " )\n", + " return action_id\n", + "\n", + "# Use this in your Jupyter notebook cell\n", + "action_id = await store_program()\n", + "print(f\"Action ID: {action_id}\")\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Have the Patient store a secret on the network such that:\n", + "- The Patient has all the regular persmissions\n", + "- Monadic is able to modify permissions and compute on the secret\n", + "- Snipper is able to compute on the secret\n", + "\n", + "TODO: Establish a chain by having Monadic actually assign compute access to Snipper" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "ExecuteTime": { + "end_time": "2024-08-09T23:28:54.210051Z", + "start_time": "2024-08-09T23:28:52.165103Z" + } + }, + "outputs": [], + "source": [ + "program_id = f\"{monadic_user_id}/{program_name}\"\n", + "\n", + "new_secret = nillion.NadaValues(\n", + " {\n", + " \"foo\": nillion.SecretInteger(2),\n", + " }\n", + ")\n", + "\n", + "# Set permissions for the client to compute on the program\n", + "permissions = nillion.Permissions.default_for_user(patient_user_id)\n", + "permissions.add_update_permissions(set([monadic_user_id]))\n", + "permissions.add_compute_permissions({monadic_user_id: {program_id}})\n", + "permissions.add_compute_permissions({snipper_user_id: {program_id}})\n", + "\n", + "# Pay for and store the secret in the network and print the returned store_id\n", + "receipt_store = await get_quote_and_pay(\n", + " patient_client,\n", + " nillion.Operation.store_values(new_secret, ttl_days=5),\n", + " payments_wallet,\n", + " payments_client,\n", + " cluster_id,\n", + ")\n", + "# Store a secret\n", + "store_id = await patient_client.store_values(\n", + " cluster_id, new_secret, permissions, receipt_store\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Have Monadic run the stored program on the stored secret\n", + "\n", + "TODO: Have Snipper run the stored program on the stored secret" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "ExecuteTime": { + "end_time": "2024-08-09T23:28:59.264419Z", + "start_time": "2024-08-09T23:28:57.193511Z" + } + }, + "outputs": [], + "source": [ + "import os\n", + "\n", + "os.environ['RUST_BACKTRACE'] = 'full'\n", + "\n", + "party_name = \"Party1\"\n", + "compute_bindings = nillion.ProgramBindings(program_id)\n", + "compute_bindings.add_input_party(party_name, monadic_party_id)\n", + "compute_bindings.add_output_party(party_name, monadic_party_id)\n", + "\n", + "computation_time_secrets = nillion.NadaValues({})\n", + "\n", + "# Pay for the compute\n", + "receipt_compute = await get_quote_and_pay(\n", + " monadic_client,\n", + " nillion.Operation.compute(program_id, computation_time_secrets),\n", + " payments_wallet,\n", + " payments_client,\n", + " cluster_id,\n", + ")\n", + "\n", + "# Compute on the secret\n", + "compute_id = await monadic_client.compute(\n", + " cluster_id,\n", + " compute_bindings,\n", + " [store_id],\n", + " computation_time_secrets,\n", + " receipt_compute,\n", + ")\n", + "\n", + "# 8. Return the computation result\n", + "print(f\"The computation was sent to the network. compute_id: {compute_id}\")\n", + "while True:\n", + " compute_event = await monadic_client.next_compute_event()\n", + " if isinstance(compute_event, nillion.ComputeFinishedEvent):\n", + " print(f\"✅ Compute complete for compute_id {compute_event.uuid}\")\n", + " print(f\"🖥️ The result is {compute_event.result.value}\")\n", + " break" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now have Snipper run the program" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "ExecuteTime": { + "end_time": "2024-08-09T23:41:25.749809Z", + "start_time": "2024-08-09T23:41:23.044687Z" + } + }, + "outputs": [], + "source": [ + "party_name = \"Party1\"\n", + "compute_bindings = nillion.ProgramBindings(program_id)\n", + "compute_bindings.add_input_party(party_name, snipper_party_id)\n", + "compute_bindings.add_output_party(party_name, snipper_party_id)\n", + "\n", + "computation_time_secrets = nillion.NadaValues({})\n", + "\n", + "# Pay for the compute\n", + "receipt_compute = await get_quote_and_pay(\n", + " snipper_client,\n", + " nillion.Operation.compute(program_id, computation_time_secrets),\n", + " payments_wallet,\n", + " payments_client,\n", + " cluster_id,\n", + ")\n", + "\n", + "# Compute on the secret\n", + "compute_id = await snipper_client.compute(\n", + " cluster_id,\n", + " compute_bindings,\n", + " [store_id],\n", + " computation_time_secrets,\n", + " receipt_compute,\n", + ")\n", + "\n", + "# 8. Return the computation result\n", + "print(f\"The computation was sent to the network. compute_id: {compute_id}\")\n", + "while True:\n", + " compute_event = await snipper_client.next_compute_event()\n", + " if isinstance(compute_event, nillion.ComputeFinishedEvent):\n", + " print(f\"✅ Compute complete for compute_id {compute_event.uuid}\")\n", + " print(f\"🖥️ The result is {compute_event.result.value}\")\n", + " break" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "colab": { + "provenance": [] + }, + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.2" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} From 3313db91193b5474d5631d9c013490c2b5a2998e Mon Sep 17 00:00:00 2001 From: aeesh Date: Thu, 24 Oct 2024 19:23:32 +0200 Subject: [PATCH 2/2] draft --- .../e2e_draft.ipynb} | 473 +++++++----------- 1 file changed, 177 insertions(+), 296 deletions(-) rename services/{e2e.ipynb => nillion-interactor/e2e_draft.ipynb} (53%) diff --git a/services/e2e.ipynb b/services/nillion-interactor/e2e_draft.ipynb similarity index 53% rename from services/e2e.ipynb rename to services/nillion-interactor/e2e_draft.ipynb index 1c47c62..614cd61 100644 --- a/services/e2e.ipynb +++ b/services/nillion-interactor/e2e_draft.ipynb @@ -1,46 +1,43 @@ { "cells": [ { - "cell_type": "markdown", - "metadata": { - "id": "JaUba7vsukRz" - }, - "source": [ - "This workbook represent an end to end test of the Nillion network. It will test the following:\n", - "1. A user (patient) uploading their data in encrypted form and providing access to Monadic\n", - "2. Monadic giving compute access to Snipper, a third party\n", - "3. Snipper registering a program and running in on the patient's encrypted data\n", - "\n", - "Before running this workbook, ensure Nillion Devnet is running. " - ] - }, - { - "cell_type": "markdown", + "cell_type": "code", + "execution_count": null, "metadata": {}, + "outputs": [], "source": [ - "Install all Python prerequisites. " + "%pip install --upgrade nada-dsl\n", + "%pip install --upgrade py-nillion-client\n", + "%pip install --upgrade nillion-python-helpers\n", + "%pip install python-dotenv==1.0.0" ] }, { "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2024-08-09T19:26:51.222994Z", - "start_time": "2024-08-09T19:26:43.883908Z" - }, - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "JAGtpt87u119", - "outputId": "2d8deba3-069f-4449-df93-f58ba31841f5" - }, - "outputs": [], + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Name: py-nillion-client\n", + "Version: 0.6.0\n", + "Summary: Python client for Nillion network and utilities.\n", + "Home-page: \n", + "Author: \n", + "Author-email: \n", + "License: Apache-2.0\n", + "Location: /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages\n", + "Requires: protobuf\n", + "Required-by: nada-numpy, nillion-python-helpers\n", + "Note: you may need to restart the kernel to use updated packages.\n" + ] + } + ], "source": [ - "%pip install nada-dsl==0.6.0\n", - "%pip install py-nillion-client==0.6.0\n", - "%pip install nillion-python-helpers==0.2.3\n", - "%pip install python-dotenv==1.0.0\n" + "# %pip show nada-dsl\n", + "%pip show py-nillion-client\n" ] }, { @@ -52,14 +49,8 @@ }, { "cell_type": "code", - "execution_count": 2, - "metadata": { - "ExecuteTime": { - "end_time": "2024-08-09T23:28:05.762189Z", - "start_time": "2024-08-09T23:28:05.723159Z" - }, - "id": "EQCfD717Sb-M" - }, + "execution_count": 3, + "metadata": {}, "outputs": [], "source": [ "import py_nillion_client as nillion\n", @@ -83,17 +74,7 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2024-08-09T23:28:08.870617Z", - "start_time": "2024-08-09T23:28:08.850035Z" - }, - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "XWsJmklOEeh1", - "outputId": "fff3de58-4f50-4e09-99f9-d7b6cdb943ed" - }, + "metadata": {}, "outputs": [], "source": [ "import os\n", @@ -119,14 +100,19 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2024-08-09T23:28:12.833625Z", - "start_time": "2024-08-09T23:28:12.815576Z" + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Cluster ID: 9e68173f-9c23-4acc-ba81-4f079b639964\n", + "Chain ID: nillion-chain-devnet\n", + "GRPC Endpoint: localhost:26649\n" + ] } - }, - "outputs": [], + ], "source": [ "cluster_id = os.getenv('NILLION_CLUSTER_ID')\n", "chain_id = os.getenv('NILLION_NILCHAIN_CHAIN_ID')\n", @@ -146,13 +132,8 @@ }, { "cell_type": "code", - "execution_count": 5, - "metadata": { - "ExecuteTime": { - "end_time": "2024-08-09T23:28:16.326786Z", - "start_time": "2024-08-09T23:28:16.320243Z" - } - }, + "execution_count": 6, + "metadata": {}, "outputs": [], "source": [ "import uuid\n", @@ -169,13 +150,8 @@ }, { "cell_type": "code", - "execution_count": 6, - "metadata": { - "ExecuteTime": { - "end_time": "2024-08-09T23:28:19.828183Z", - "start_time": "2024-08-09T23:28:19.615786Z" - } - }, + "execution_count": 7, + "metadata": {}, "outputs": [], "source": [ "monadic_seed = \"monadic_seed\"\n", @@ -194,13 +170,8 @@ }, { "cell_type": "code", - "execution_count": 7, - "metadata": { - "ExecuteTime": { - "end_time": "2024-08-09T23:28:22.512975Z", - "start_time": "2024-08-09T23:28:22.489237Z" - } - }, + "execution_count": 8, + "metadata": {}, "outputs": [], "source": [ "snipper_seed = \"snipper_seed\"\n", @@ -219,13 +190,8 @@ }, { "cell_type": "code", - "execution_count": 8, - "metadata": { - "ExecuteTime": { - "end_time": "2024-08-09T23:28:28.760101Z", - "start_time": "2024-08-09T23:28:28.734404Z" - } - }, + "execution_count": 9, + "metadata": {}, "outputs": [], "source": [ "patient_seed = \"patient_seed\"\n", @@ -244,15 +210,17 @@ }, { "cell_type": "code", - "execution_count": 9, - "metadata": { - "ExecuteTime": { - "end_time": "2024-08-09T23:28:31.282228Z", - "start_time": "2024-08-09T23:28:31.238065Z" - }, - "id": "pkaCYaErQ8kf" - }, - "outputs": [], + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Deprecation warning: payments_endpoint should start with http:// or https://\n" + ] + } + ], "source": [ "payments_config = create_payments_config(chain_id, grpc_endpoint)\n", "payments_client = LedgerClient(payments_config)\n", @@ -271,14 +239,8 @@ }, { "cell_type": "code", - "execution_count": 10, - "metadata": { - "ExecuteTime": { - "end_time": "2024-08-09T23:28:33.143041Z", - "start_time": "2024-08-09T23:28:33.134076Z" - }, - "id": "rEr0_JkMuVci" - }, + "execution_count": 11, + "metadata": {}, "outputs": [], "source": [ "program_name = \"double\"\n", @@ -289,46 +251,26 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "As a baseline, let's ensure that the user can store the program and run it on their own secret. " + "Patient Assigns Permissions to Monadic\n", + "##### The Patient stores a secret and grants Monadic the ability to modify permissions and compute on the secret." ] }, { "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2024-08-09T23:28:41.524938Z", - "start_time": "2024-08-09T23:28:35.164639Z" + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Getting quote for operation...\n", + "Quote cost is 482 unil\n", + "Submitting payment receipt 482 unil, tx hash D8D00E695B33B011CD770BE42C9C6823987149AF19A566275BAC7771015C96F3\n" + ] } - }, - "outputs": [], + ], "source": [ - "import os\n", - "\n", - "os.environ['RUST_BACKTRACE'] = '1'\n", - "\n", - "print(\"The patient is storing the program on the network\")\n", - "\n", - "async def store_program():\n", - " receipt_store_program = await get_quote_and_pay(\n", - " patient_client,\n", - " nillion.Operation.store_program(program_mir_path),\n", - " payments_wallet,\n", - " payments_client,\n", - " cluster_id,\n", - " )\n", - "\n", - " # Store the program\n", - " action_id = await patient_client.store_program(\n", - " cluster_id, program_name, program_mir_path, receipt_store_program\n", - " )\n", - " return action_id\n", - "\n", - "action_id = await store_program()\n", - "print(f\"Action ID: {action_id}\")\n", - "\n", - "print(\"The patient is storing a secret on the network\")\n", - "\n", "program_id = f\"{patient_user_id}/{program_name}\"\n", "\n", "new_secret = nillion.NadaValues(\n", @@ -339,140 +281,20 @@ "\n", "# Set permissions for the client to compute on the program\n", "permissions = nillion.Permissions.default_for_user(patient_user_id)\n", - "permissions.add_compute_permissions({patient_user_id: {program_id}})\n", "\n", - "# Pay for and store the secret in the network and print the returned store_id\n", - "receipt_store = await get_quote_and_pay(\n", - " patient_client,\n", - " nillion.Operation.store_values(new_secret, ttl_days=5),\n", - " payments_wallet,\n", - " payments_client,\n", - " cluster_id,\n", - ")\n", - "# Store a secret\n", - "store_id = await patient_client.store_values(\n", - " cluster_id, new_secret, permissions, receipt_store\n", - ")\n", - "\n", - "print(\"The patient is running the program on the secret..\")\n", - "\n", - "party_name = \"Party1\"\n", - "compute_bindings = nillion.ProgramBindings(program_id)\n", - "compute_bindings.add_input_party(party_name, patient_party_id)\n", - "compute_bindings.add_output_party(party_name, patient_party_id)\n", - "computation_time_secrets = nillion.NadaValues({})\n", - "\n", - "# Pay for the compute\n", - "receipt_compute = await get_quote_and_pay(\n", - " patient_client,\n", - " nillion.Operation.compute(program_id, computation_time_secrets),\n", - " payments_wallet,\n", - " payments_client,\n", - " cluster_id,\n", - ")\n", + "# Grant Monadic permission to compute and modify permissions\n", + "permissions.add_update_permissions(set([monadic_user_id]))\n", + "permissions.add_compute_permissions({monadic_user_id: {program_id}})\n", "\n", - "# Compute on the secret\n", - "compute_id = await patient_client.compute(\n", - " cluster_id,\n", - " compute_bindings,\n", - " [store_id],\n", - " computation_time_secrets,\n", - " receipt_compute,\n", - ")\n", "\n", - "# 8. Return the computation result\n", - "print(f\"The computation was sent to the network. compute_id: {compute_id}\")\n", - "while True:\n", - " compute_event = await patient_client.next_compute_event()\n", - " if isinstance(compute_event, nillion.ComputeFinishedEvent):\n", - " print(f\"✅ Compute complete for compute_id {compute_event.uuid}\")\n", - " print(f\"🖥️ The result is {compute_event.result.value}\")\n", - " break" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Have Monadic store the program on the network\n", + "# # ERROR: AttributeError: 'builtins.Permissions' object has no attribute 'allow_delegate_compute'\n", + "# permissions = nillion.Permissions.default_for_user(patient_user_id)\n", + "# permissions.allow_delegate_compute(monadic_user_id)\n", "\n", - "TODO: Also have Snipper save the program and replicate the computation" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2024-08-09T23:28:49.395066Z", - "start_time": "2024-08-09T23:28:47.351151Z" - }, - "colab": { - "base_uri": "https://localhost:8080/", - "height": 211 - }, - "id": "wgS0N715Qid2", - "outputId": "eb833ff1-b29c-492b-b3c4-271a08a86b51" - }, - "outputs": [], - "source": [ - "async def store_program():\n", - " receipt_store_program = await get_quote_and_pay(\n", - " monadic_client,\n", - " nillion.Operation.store_program(program_mir_path),\n", - " payments_wallet,\n", - " payments_client,\n", - " cluster_id,\n", - " )\n", - "\n", - " # Store the program\n", - " action_id = await monadic_client.store_program(\n", - " cluster_id, program_name, program_mir_path, receipt_store_program\n", - " )\n", - " return action_id\n", - "\n", - "# Use this in your Jupyter notebook cell\n", - "action_id = await store_program()\n", - "print(f\"Action ID: {action_id}\")\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Have the Patient store a secret on the network such that:\n", - "- The Patient has all the regular persmissions\n", - "- Monadic is able to modify permissions and compute on the secret\n", - "- Snipper is able to compute on the secret\n", - "\n", - "TODO: Establish a chain by having Monadic actually assign compute access to Snipper" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2024-08-09T23:28:54.210051Z", - "start_time": "2024-08-09T23:28:52.165103Z" - } - }, - "outputs": [], - "source": [ - "program_id = f\"{monadic_user_id}/{program_name}\"\n", "\n", - "new_secret = nillion.NadaValues(\n", - " {\n", - " \"foo\": nillion.SecretInteger(2),\n", - " }\n", - ")\n", + "# # Grant Snipper permission to compute\n", + "# permissions.add_compute_permissions({snipper_user_id: {program_id}})\n", "\n", - "# Set permissions for the client to compute on the program\n", - "permissions = nillion.Permissions.default_for_user(patient_user_id)\n", - "permissions.add_update_permissions(set([monadic_user_id]))\n", - "permissions.add_compute_permissions({monadic_user_id: {program_id}})\n", - "permissions.add_compute_permissions({snipper_user_id: {program_id}})\n", "\n", "# Pay for and store the secret in the network and print the returned store_id\n", "receipt_store = await get_quote_and_pay(\n", @@ -482,6 +304,7 @@ " payments_client,\n", " cluster_id,\n", ")\n", + "\n", "# Store a secret\n", "store_id = await patient_client.store_values(\n", " cluster_id, new_secret, permissions, receipt_store\n", @@ -492,21 +315,27 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Have Monadic run the stored program on the stored secret\n", - "\n", - "TODO: Have Snipper run the stored program on the stored secret" + "Have Monadic run the stored program on the stored secret" ] }, { "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2024-08-09T23:28:59.264419Z", - "start_time": "2024-08-09T23:28:57.193511Z" + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Getting quote for operation...\n", + "Quote cost is 3 unil\n", + "Submitting payment receipt 3 unil, tx hash 77154C1832C6BD7B798D7DA24F592BC77FC4DF159D14AB248C1D7D77FA293E11\n", + "The computation was sent to the network. compute_id: 1d62a176-78dc-4e78-8518-6d5f982ce971\n", + "✅ Compute complete for compute_id 1d62a176-78dc-4e78-8518-6d5f982ce971\n", + "🖥️ The result is {'my_output': 4}\n" + ] } - }, - "outputs": [], + ], "source": [ "import os\n", "\n", @@ -551,25 +380,87 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Now have Snipper run the program" + "~IN PROGRESS~: Have Snipper run the stored program on the stored secret" ] }, { "cell_type": "code", - "execution_count": null, - "metadata": { - "ExecuteTime": { - "end_time": "2024-08-09T23:41:25.749809Z", - "start_time": "2024-08-09T23:41:23.044687Z" + "execution_count": 31, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Getting quote for operation...\n", + "Quote cost is 2 unil\n", + "Submitting payment receipt 2 unil, tx hash 8D681DDCFBD3A19FCD8E5D71FA5F43BE1C4630AB7056B6D147081F7C7993FAF9\n", + "Updated permissions: \n", + "Getting quote for operation...\n", + "Quote cost is 2 unil\n", + "Submitting payment receipt 2 unil, tx hash 923355F0E7EA0823468932C4C7AD290936D55BB4B4B4E12FF2376B8B3EEEDB3C\n" + ] + }, + { + "ename": "ComputeError", + "evalue": "updating permissions: compute unexpected error: user does not have permissions for action", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mComputeError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[31], line 41\u001b[0m\n\u001b[1;32m 32\u001b[0m receipt_update_permissions \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mawait\u001b[39;00m get_quote_and_pay(\n\u001b[1;32m 33\u001b[0m monadic_client,\n\u001b[1;32m 34\u001b[0m nillion\u001b[38;5;241m.\u001b[39mOperation\u001b[38;5;241m.\u001b[39mupdate_permissions(),\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 37\u001b[0m cluster_id,\n\u001b[1;32m 38\u001b[0m )\n\u001b[1;32m 40\u001b[0m \u001b[38;5;66;03m# ComputeError: updating permissions: compute unexpected error: user does not have permissions for action\u001b[39;00m\n\u001b[0;32m---> 41\u001b[0m update_id \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mawait\u001b[39;00m monadic_client\u001b[38;5;241m.\u001b[39mupdate_permissions(\n\u001b[1;32m 42\u001b[0m cluster_id, store_id, current_permissions, receipt_update_permissions\n\u001b[1;32m 43\u001b[0m )\n\u001b[1;32m 44\u001b[0m \u001b[38;5;66;03m########################################################################################################\u001b[39;00m\n\u001b[1;32m 48\u001b[0m computation_time_secrets \u001b[38;5;241m=\u001b[39m nillion\u001b[38;5;241m.\u001b[39mNadaValues({})\n", + "\u001b[0;31mComputeError\u001b[0m: updating permissions: compute unexpected error: user does not have permissions for action" + ] } - }, - "outputs": [], + ], "source": [ + "import os\n", + "\n", + "os.environ['RUST_BACKTRACE'] = 'full'\n", + "\n", "party_name = \"Party1\"\n", "compute_bindings = nillion.ProgramBindings(program_id)\n", "compute_bindings.add_input_party(party_name, snipper_party_id)\n", "compute_bindings.add_output_party(party_name, snipper_party_id)\n", "\n", + "########################################################################################################\n", + "# # Grant Snipper permission to compute\n", + "# permissions.add_compute_permissions({snipper_user_id: {program_id}})\n", + "\n", + "# Retrieve current permissions for secret\n", + "receipt_retrieve_permissions = await get_quote_and_pay(\n", + " patient_client,\n", + " nillion.Operation.retrieve_permissions(),\n", + " payments_wallet,\n", + " payments_client,\n", + " cluster_id,\n", + ")\n", + "\n", + "# Grant Snipper permission to compute\n", + "# sidenote: this method still relies on \"patient_client\" instead of \"monadic_client\"\n", + "# to retrieve current permissions and make the update\n", + "current_permissions = await patient_client.retrieve_permissions(cluster_id, store_id, receipt_retrieve_permissions)\n", + "current_permissions.add_compute_permissions({snipper_user_id: {program_id}})\n", + "print(f\"Updated permissions: {current_permissions}\")\n", + "\n", + "\n", + "# Get cost quote, then pay for operation to update permissions\n", + "receipt_update_permissions = await get_quote_and_pay(\n", + " monadic_client,\n", + " nillion.Operation.update_permissions(),\n", + " payments_wallet,\n", + " payments_client,\n", + " cluster_id,\n", + ")\n", + "\n", + "# ComputeError: updating permissions: compute unexpected error: user does not have permissions for action\n", + "update_id = await monadic_client.update_permissions(\n", + " cluster_id, store_id, current_permissions, receipt_update_permissions\n", + ")\n", + "########################################################################################################\n", + "\n", + "\n", + "\n", "computation_time_secrets = nillion.NadaValues({})\n", "\n", "# Pay for the compute\n", @@ -599,21 +490,11 @@ " print(f\"🖥️ The result is {compute_event.result.value}\")\n", " break" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { - "colab": { - "provenance": [] - }, "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": "Python 3", "language": "python", "name": "python3" }, @@ -631,5 +512,5 @@ } }, "nbformat": 4, - "nbformat_minor": 0 + "nbformat_minor": 2 }