Skip to content

Commit

Permalink
Merge pull request #1 from wwwehr/add_notebook_and_google_colab_link
Browse files Browse the repository at this point in the history
ported example to notebook and added google colab link
  • Loading branch information
lapets authored Dec 13, 2023
2 parents f837ceb + a243503 commit 03ecf86
Show file tree
Hide file tree
Showing 2 changed files with 287 additions and 1 deletion.
6 changes: 5 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ tinynmc

Minimal pure-Python implementation of a secure multi-party computation (MPC) `protocol for evaluating arithmetic sum-of-products expressions <https://eprint.iacr.org/2023/1740>`__ via a non-interactive computation phase.

|pypi| |readthedocs| |actions| |coveralls|
|pypi| |readthedocs| |actions| |coveralls| |colab|

.. |pypi| image:: https://badge.fury.io/py/tinynmc.svg
:target: https://badge.fury.io/py/tinynmc
Expand All @@ -22,6 +22,10 @@ Minimal pure-Python implementation of a secure multi-party computation (MPC) `pr
:target: https://coveralls.io/github/nillion-oss/tinynmc?branch=main
:alt: Coveralls test coverage summary.

.. |colab| image:: https://colab.research.google.com/assets/colab-badge.svg
:target: https://colab.research.google.com/github/nillion-oss/tinynmc/blob/main/notebooks/basic.ipynb
:alt: Open notebook in Google Colab.

Installation and Usage
----------------------

Expand Down
282 changes: 282 additions & 0 deletions notebooks/basic.ipynb
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
}
]
}
]
}

0 comments on commit 03ecf86

Please sign in to comment.