Repository: OpenMined/PySyft

Issue:
generate_triple in base.py
**Describe the bug**
Cryptography logic is inside of the generic worker class, which is not a proper decoupling of messaging infrastructure from cryptography protocols.

**To Reproduce**
Visit... https://github.com/OpenMined/PySyft/blob/dev/syft/workers/base.py#L825

**Expected behavior**
This method should instead live in a new file syft/frameworks/torch/crypto/beaver.py as a method called "request_triple" where you also pass in the worker you'd like to request the triple from.





Discussion:
I would like to work on it. 

Resolving patch:
diff --git a/syft/frameworks/torch/crypto/beaver.py b/syft/frameworks/torch/crypto/beaver.py
new file mode 100644
--- /dev/null
+++ b/syft/frameworks/torch/crypto/beaver.py
@@ -0,0 +1,33 @@
+import torch
+from typing import Callable
+from syft.workers.abstract import AbstractWorker
+
+
+def request_triple(
+    crypto_provider: AbstractWorker,
+    cmd: Callable,
+    field: int,
+    a_size: tuple,
+    b_size: tuple,
+    locations: list,
+):
+    """Generates a multiplication triple and sends it to all locations.
+
+    Args:
+        crypto_provider: worker you would like to request the triple from
+        cmd: An equation in einsum notation.
+        field: An integer representing the field size.
+        a_size: A tuple which is the size that a should be.
+        b_size: A tuple which is the size that b should be.
+        locations: A list of workers where the triple should be shared between.
+
+    Returns:
+        A triple of AdditiveSharedTensors such that c_shared = cmd(a_shared, b_shared).
+    """
+    a = torch.randint(field, a_size)
+    b = torch.randint(field, b_size)
+    c = cmd(a, b)
+    a_shared = a.share(*locations, field=field, crypto_provider=crypto_provider).child
+    b_shared = b.share(*locations, field=field, crypto_provider=crypto_provider).child
+    c_shared = c.share(*locations, field=field, crypto_provider=crypto_provider).child
+    return a_shared, b_shared, c_shared
diff --git a/syft/frameworks/torch/crypto/spdz.py b/syft/frameworks/torch/crypto/spdz.py
--- a/syft/frameworks/torch/crypto/spdz.py
+++ b/syft/frameworks/torch/crypto/spdz.py
@@ -2,6 +2,7 @@
 from typing import Callable
 import syft as sy
 from syft.workers.abstract import AbstractWorker
+from syft.frameworks.torch.crypto.beaver import request_triple
 
 no_wrap = {"no_wrap": True}
 
@@ -25,7 +26,7 @@ def spdz_mul(cmd: Callable, x_sh, y_sh, crypto_provider: AbstractWorker, field:
     locations = x_sh.locations
 
     # Get triples
-    a, b, a_mul_b = crypto_provider.generate_triple(cmd, field, x_sh.shape, y_sh.shape, locations)
+    a, b, a_mul_b = request_triple(crypto_provider, cmd, field, x_sh.shape, y_sh.shape, locations)
 
     delta = x_sh - a
     epsilon = y_sh - b
diff --git a/syft/workers/base.py b/syft/workers/base.py
--- a/syft/workers/base.py
+++ b/syft/workers/base.py
@@ -818,29 +818,6 @@ def deserialized_search(self, query_items: Tuple[str]) -> List["pointers.Pointer
         """
         return self.search(*query_items)
 
-    def generate_triple(
-        self, cmd: Callable, field: int, a_size: tuple, b_size: tuple, locations: list
-    ):
-        """Generates a multiplication triple and sends it to all locations.
-
-        Args:
-            cmd: An equation in einsum notation.
-            field: An integer representing the field size.
-            a_size: A tuple which is the size that a should be.
-            b_size: A tuple which is the size that b should be.
-            locations: A list of workers where the triple should be shared between.
-
-        Returns:
-            A triple of AdditiveSharedTensors such that c_shared = cmd(a_shared, b_shared).
-        """
-        a = self.torch.randint(field, a_size)
-        b = self.torch.randint(field, b_size)
-        c = cmd(a, b)
-        a_shared = a.share(*locations, field=field, crypto_provider=self).child
-        b_shared = b.share(*locations, field=field, crypto_provider=self).child
-        c_shared = c.share(*locations, field=field, crypto_provider=self).child
-        return a_shared, b_shared, c_shared
-
     def _get_msg(self, index):
         """Returns a decrypted message from msg_history. Mostly useful for testing.
 


Test patch: