-
Notifications
You must be signed in to change notification settings - Fork 13
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 #1 from wwwehr/add_notebook_and_google_colab_link
ported example to notebook and added google colab link
- Loading branch information
Showing
2 changed files
with
287 additions
and
1 deletion.
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
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,282 @@ | ||
{ | ||
"nbformat": 4, | ||
"nbformat_minor": 0, | ||
"metadata": { | ||
"colab": { | ||
"provenance": [] | ||
}, | ||
"kernelspec": { | ||
"name": "python3", | ||
"display_name": "Python 3" | ||
}, | ||
"language_info": { | ||
"name": "python" | ||
} | ||
}, | ||
"cells": [ | ||
{ | ||
"cell_type": "markdown", | ||
"source": [ | ||
"# tinynmc\n", | ||
"https://github.com/nillion-oss/tinynmc\n", | ||
"\n", | ||
"---\n", | ||
"Minimal pure-Python implementation of a secure multi-party computation (MPC) protocol for evaluating arithmetic sum-of-products expressions via a non-interactive computation phase." | ||
], | ||
"metadata": { | ||
"id": "Kkf4IWOwxHln" | ||
} | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"source": [ | ||
"# Installation and Usage\n", | ||
"\n", | ||
"This library is available as a package on PyPI:" | ||
], | ||
"metadata": { | ||
"id": "ps_hmiPixTJe" | ||
} | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 4, | ||
"metadata": { | ||
"colab": { | ||
"base_uri": "https://localhost:8080/" | ||
}, | ||
"id": "oUPscM3Lwq1O", | ||
"outputId": "396065d1-18d2-459d-d550-b5a962ecc382" | ||
}, | ||
"outputs": [ | ||
{ | ||
"output_type": "stream", | ||
"name": "stdout", | ||
"text": [ | ||
"Collecting tinynmc\n", | ||
" Downloading tinynmc-0.2.0-py3-none-any.whl (9.1 kB)\n", | ||
"Collecting modulo~=2.1 (from tinynmc)\n", | ||
" Downloading modulo-2.1.0-py3-none-any.whl (11 kB)\n", | ||
"Collecting egcd~=0.5 (from modulo~=2.1->tinynmc)\n", | ||
" Downloading egcd-0.5.0-py3-none-any.whl (5.3 kB)\n", | ||
"Installing collected packages: egcd, modulo, tinynmc\n", | ||
"Successfully installed egcd-0.5.0 modulo-2.1.0 tinynmc-0.2.0\n" | ||
] | ||
} | ||
], | ||
"source": [ | ||
"! python -m pip install tinynmc" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"source": [ | ||
"The library can be imported in the usual way:" | ||
], | ||
"metadata": { | ||
"id": "0Hx7UnvsxZsM" | ||
} | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"source": [ | ||
"import tinynmc\n", | ||
"from tinynmc import *" | ||
], | ||
"metadata": { | ||
"id": "1-37U7O8wyXt" | ||
}, | ||
"execution_count": 6, | ||
"outputs": [] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"source": [ | ||
"# Basic Example" | ||
], | ||
"metadata": { | ||
"id": "r_CzdhwExciE" | ||
} | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"source": [ | ||
"This example involves three contributors a, b, and c (parties submitting private input values) and three nodes 0, 1, and 2 (parties performing a computation):\n", | ||
"\n" | ||
], | ||
"metadata": { | ||
"id": "kM9Wci90xiEW" | ||
} | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"source": [ | ||
"nodes = [node(), node(), node()]" | ||
], | ||
"metadata": { | ||
"id": "6Tr1LB6FxmH0" | ||
}, | ||
"execution_count": 7, | ||
"outputs": [] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"source": [ | ||
"\n", | ||
"The overall sum-of-products expression being computed is (1 * 2 * 3) + (4 * 5). First, the contributors agree on a workflow signature. The signature lists the number of factors in each term:\n", | ||
"\n" | ||
], | ||
"metadata": { | ||
"id": "Q8BbZbGWx-6J" | ||
} | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"source": [ | ||
"signature = [3, 2]" | ||
], | ||
"metadata": { | ||
"id": "PalLl1iUxoqz" | ||
}, | ||
"execution_count": 8, | ||
"outputs": [] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"source": [ | ||
"The signature must be shared with every node so that the nodes can collectively perform the preprocessing phase; this can be accomplished using any MPC protocol that supports multiplication of secret-shared values, such as the SPDZ protocol (a similarly simple implementation of which can be seen in the TinySMPC library):\n", | ||
"\n", | ||
">" | ||
], | ||
"metadata": { | ||
"id": "8GPVUCL6yA0A" | ||
} | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"source": [ | ||
"preprocess(signature, nodes)" | ||
], | ||
"metadata": { | ||
"id": "ettT3TYdxqTK" | ||
}, | ||
"execution_count": 9, | ||
"outputs": [] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"source": [ | ||
"Next, each factor in the workflow is contributed by one of three contributors a, b, or c, with the ownership pattern `(a * b * c) + (a * b)`. Each factor is referenced by the contributors according to its `(term_index, factor_index)` coordinate within the overall expression: `((0, 0) * (0, 1)) + ((1, 0) * (1, 1) * (1, 2))`.\n", | ||
"\n", | ||
"Each contributor can convert its coordinate-value pairs into masked factors by (1) requesting the multiplicative shares of the masks for each coordinate, and (2) masking its factors at each coordinate using those masks:\n", | ||
"\n", | ||
">" | ||
], | ||
"metadata": { | ||
"id": "2_7j_wY0yD9c" | ||
} | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"source": [ | ||
"coords_to_values_a = {(0, 0): 1, (1, 0): 4}\n", | ||
"masks_from_nodes_a = [node.masks(coords_to_values_a.keys()) for node in nodes]\n", | ||
"masked_factors_a = masked_factors(coords_to_values_a, masks_from_nodes_a)\n", | ||
"\n", | ||
"coords_to_values_b = {(0, 1): 2, (1, 1): 5}\n", | ||
"masks_from_nodes_b = [node.masks(coords_to_values_b.keys()) for node in nodes]\n", | ||
"masked_factors_b = masked_factors(coords_to_values_b, masks_from_nodes_b)\n", | ||
"\n", | ||
"coords_to_values_c = {(0, 2): 3}\n", | ||
"masks_from_nodes_c = [node.masks(coords_to_values_c.keys()) for node in nodes]\n", | ||
"masked_factors_c = masked_factors(coords_to_values_c, masks_from_nodes_c)" | ||
], | ||
"metadata": { | ||
"id": "ipeZWf37xtQ4" | ||
}, | ||
"execution_count": 10, | ||
"outputs": [] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"source": [ | ||
"\n", | ||
"Each contributor then broadcasts all of its masked factors to every node, so every node receives all of the masked factors from all of the contributors:\n" | ||
], | ||
"metadata": { | ||
"id": "DX_CqFZgyGIb" | ||
} | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"source": [ | ||
"broadcast = [masked_factors_a, masked_factors_b, masked_factors_c]" | ||
], | ||
"metadata": { | ||
"id": "Ql8DzshIxygP" | ||
}, | ||
"execution_count": 11, | ||
"outputs": [] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"source": [ | ||
"\n", | ||
"\n", | ||
"Then, every node can locally compute its share of the overall result:\n" | ||
], | ||
"metadata": { | ||
"id": "CeCbpMQ7yI6b" | ||
} | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"source": [ | ||
"result_share_at_node_0 = nodes[0].compute(signature, broadcast)\n", | ||
"result_share_at_node_1 = nodes[1].compute(signature, broadcast)\n", | ||
"result_share_at_node_2 = nodes[2].compute(signature, broadcast)" | ||
], | ||
"metadata": { | ||
"id": "PA6hoHNkx1DU" | ||
}, | ||
"execution_count": 12, | ||
"outputs": [] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"source": [ | ||
"\n", | ||
"Finally, the result can be reconstructed via summation from the result shares received from the nodes:\n" | ||
], | ||
"metadata": { | ||
"id": "3EJeOxAAyLgj" | ||
} | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"source": [ | ||
"int(sum([result_share_at_node_0, result_share_at_node_1, result_share_at_node_2]))" | ||
], | ||
"metadata": { | ||
"colab": { | ||
"base_uri": "https://localhost:8080/" | ||
}, | ||
"id": "JdkKtmYyx4Qz", | ||
"outputId": "afdd0edc-2e92-43f8-d0b3-6a368c4d7c65" | ||
}, | ||
"execution_count": 13, | ||
"outputs": [ | ||
{ | ||
"output_type": "execute_result", | ||
"data": { | ||
"text/plain": [ | ||
"26" | ||
] | ||
}, | ||
"metadata": {}, | ||
"execution_count": 13 | ||
} | ||
] | ||
} | ||
] | ||
} |