internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: OpenMined/PySyft

Issue:
Move() on same machine
Dear all,

I was not sure whether to classify this as a "bug" or "new feature", please move it in case this is wrong.
Is the behavior of the move() method intended to throw an error, when trying to move an object to a virtual worker that already possesses the object?
In case this happens, a objectnotfounderror is raised: 

_ObjectNotFoundError: Object "56137057453" not found on worker!!! You just tried to interact with an object ID:56137057453 on <VirtualWorker id:manager_alice #objects:12> which does not exist!!! Use .send() and .get() on all your tensors to make sure they're on the same machines. If you think this tensor does exist, check the ._objects dictionary on the worker and see for yourself!!! The most common reason this error happens is because someone calls .get() on the object's pointer without realizing it (which deletes the remote object and sends it to the pointer). Check your code to make sure you haven't already called .get() on this pointer!!!_

Of course one can handle this in the control logic by checking the object ownership before calling the move method, but I think it would be nice if the move() method just ignores the request in case one tries to move objects that a worker already possesses.
When looping over multiple workers this would simplify the control logic.




Discussion:

Resolving patch:
diff --git a/syft/generic/pointers/pointer_tensor.py b/syft/generic/pointers/pointer_tensor.py
--- a/syft/generic/pointers/pointer_tensor.py
+++ b/syft/generic/pointers/pointer_tensor.py
@@ -274,6 +274,9 @@ def move(self, destination: AbstractWorker, requires_grad: bool = False):
         if self.owner.id == destination.id:
             return self.get()
 
+        if self.location.id == destination.id:
+            return self
+
         ptr = self.remote_send(destination, requires_grad=requires_grad)
 
         # We make the pointer point at the remote value. As the id doesn't change,


Test patch:
diff --git a/test/torch/pointers/test_pointer_tensor.py b/test/torch/pointers/test_pointer_tensor.py
--- a/test/torch/pointers/test_pointer_tensor.py
+++ b/test/torch/pointers/test_pointer_tensor.py
@@ -329,6 +329,12 @@ def test_move(workers):
     z = y.move(me)
     assert (z == t).all()
 
+    # Move object to same location
+    alice.clear_objects()
+    t = torch.tensor([1.0, 2, 3, 4, 5]).send(bob)
+    t = t.move(bob)
+    assert torch.all(torch.eq(t.get(), torch.tensor([1.0, 2, 3, 4, 5])))
+
 
 def test_combine_pointers(workers):
     """
Repository: OpenMined/PySyft

Issue:
Method to check if support for framework exists
**Is your feature request related to a problem? Please describe.**
Have a method that checks if a worker can add support for a specific framework.

**Describe the solution you'd like**
A method in the ```BaseWorker``` which receives a framework name and it returns ```True``` or ```False``` depending if there exists support for a specific framework.


Discussion:

Resolving patch:
diff --git a/syft/workers/base.py b/syft/workers/base.py
--- a/syft/workers/base.py
+++ b/syft/workers/base.py
@@ -15,7 +15,7 @@
 from syft.execution.communication import CommunicationAction
 from syft.generic.frameworks.hook import hook_args
 from syft.generic.frameworks.remote import Remote
-from syft.generic.frameworks.types import FrameworkTensorType
+from syft.generic.frameworks.types import FrameworkTensorType, framework_packages
 from syft.generic.frameworks.types import FrameworkTensor
 from syft.generic.frameworks.types import FrameworkShape
 from syft.generic.object_storage import ObjectStore
@@ -1273,3 +1273,12 @@ def force_detail(worker: AbstractWorker, worker_tuple: tuple) -> tuple:
                 worker.object_store.rm_obj(obj.id)
 
         return result
+
+    @classmethod
+    def is_framework_supported(cls, framework: str) -> bool:
+        """
+        Returns True if framework is supported, else returns False.
+        :param framework: string
+        :return: True/False
+        """
+        return framework.lower() in framework_packages


Test patch:
diff --git a/test/workers/test_base.py b/test/workers/test_base.py
--- a/test/workers/test_base.py
+++ b/test/workers/test_base.py
@@ -130,3 +130,10 @@ def test_send_command_not_whitelisted(hook, workers):
 
             with pytest.raises(AttributeError):
                 getattr(attr, method_not_exist)
+
+
+def test_is_framework_supported(hook):
+    worker = sy.VirtualWorker(hook, id="worker")
+    assert worker.is_framework_supported("torch") == True
+    assert sy.VirtualWorker.is_framework_supported("torch") == True
+    assert worker.is_framework_supported("mock_framework") == False
Repository: OpenMined/PySyft

Issue:
Disable manual register() ids in syft.grid.register()
**Is your feature request related to a problem? Please describe.**
It is a security risk for people to specify their own IDs given that GridNetwork will let you connect to anyone whose id you already know. Thus, we should disable the ability for people to specify their own ID and replace it with a randomly generated hash.

This hash should be printed with clear instructions ("Send this to whomever you'd like to connect with") when register() is called.


Discussion:

Resolving patch:
diff --git a/syft/grid/__init__.py b/syft/grid/__init__.py
--- a/syft/grid/__init__.py
+++ b/syft/grid/__init__.py
@@ -1,13 +1,12 @@
 from .network import Network
+import uuid
 
 DEFAULT_NETWORK_URL = "ws://ec2-13-59-45-128.us-east-2.compute.amazonaws.com"
 
 
-def register(node_id: str, **kwargs):
+def register(**kwargs):
     """ Add this process as a new peer registering it in the grid network.
         
-        Args:
-            node_id: Id used to identify this node.
         Returns:
             peer: Peer Network instance.
     """
@@ -16,6 +15,8 @@ def register(node_id: str, **kwargs):
     else:
         args = kwargs
 
-    peer = Network(node_id, **args)
+    peer_id = str(uuid.uuid4())
+    peer = Network(peer_id, **args)
     peer.start()
+
     return peer


Test patch:
Repository: OpenMined/PySyft

Issue:
sy.grid.register() should print useful information
**Is your feature request related to a problem? Please describe.**
When registering a node on OpenGrid, we want to convey some information to the user using sys.stdout.write()

A few things we thought to add.

- Information: connecting to opengrid...etc.
    - Information: Can I connect to the main grid node... graceful error message if you can't.
- Disclaimer: OpenGrid is an experimental feature currently in alpha. Do not use this to protect real-world data.
- Where to get Help:
    - Join our slack (slack.openmined.org) and ask for help in the #lib_syft channel.
    - File a Github Issue: https://github.com/OpenMined/PySyft and add the string "#opengrid" in the issue title.
    



Discussion:
It would also be great if this information included a "want to join development? Apply to join the PyGrid team!" and there's a link.

Resolving patch:
diff --git a/syft/grid/__init__.py b/syft/grid/__init__.py
--- a/syft/grid/__init__.py
+++ b/syft/grid/__init__.py
@@ -1,4 +1,5 @@
 from .network import Network
+import sys
 import uuid
 
 DEFAULT_NETWORK_URL = "ws://ec2-13-59-45-128.us-east-2.compute.amazonaws.com"
@@ -16,7 +17,32 @@ def register(**kwargs):
         args = kwargs
 
     peer_id = str(uuid.uuid4())
+    sys.stdout.write(
+        "Connecting to OpenGrid (" + "\033[94m" + DEFAULT_NETWORK_URL + "\033[0m" + ") ... "
+    )
     peer = Network(peer_id, **args)
+
+    sys.stdout.write("\033[92m" + "OK" + "\033[0m" + "\n")
+    sys.stdout.write("Peer ID: " + peer_id + "\n")
+
+    sys.stdout.write(
+        "\033[93m" + "DISCLAIMER" + "\033[0m"
+        ":"
+        + "\033[1m"
+        + " OpenGrid is an experimental feature currently in alpha. Do not use this to protect real-world data.\n"
+        + "\033[0m"
+    )
+
+    sys.stdout.write("Where to get help: \n")
+    sys.stdout.write(
+        " - Join our slack  (https://slack.openmined.org) and ask for help in the #lib_syft channel.\n"
+    )
+    sys.stdout.write(
+        " - File a Github Issue: https://github.com/OpenMined/PySyft and add the string '#opengrid' in the issue title.\n"
+    )
+    sys.stdout.write(
+        " - Want to join in our development team? Apply here: https://forms.gle/wcH1vxzvPyDSbSVW6\n"
+    )
     peer.start()
 
     return peer


Test patch:
Repository: OpenMined/PySyft

Issue:
Calling syft.grid.register() twice should throw an informative error
**Is your feature request related to a problem? Please describe.**
If you call syft.grid.register() twice in the same python runtime it should raise an error describing that you can't do this - that they shoudl restart the python runtime and try again.


Discussion:

Resolving patch:
diff --git a/syft/grid/__init__.py b/syft/grid/__init__.py
--- a/syft/grid/__init__.py
+++ b/syft/grid/__init__.py
@@ -4,13 +4,25 @@
 
 DEFAULT_NETWORK_URL = "ws://ec2-13-59-45-128.us-east-2.compute.amazonaws.com"
 
+_registered_peer = None
+
 
 def register(**kwargs):
     """ Add this process as a new peer registering it in the grid network.
-        
+
         Returns:
             peer: Peer Network instance.
     """
+    global _registered_peer
+
+    if isinstance(_registered_peer, Network):
+        sys.stdout.write(
+            "\033[93m" + "WARNING" + "\033[0m"
+            ":" + f" You are already a registered peer!\n{_registered_peer}\n"
+        )
+
+        return _registered_peer
+
     try:
         if not kwargs:
             args = {"max_size": None, "timeout": 444, "url": DEFAULT_NETWORK_URL}
@@ -22,7 +34,7 @@ def register(**kwargs):
             "Connecting to OpenGrid (" + "\033[94m" + args["url"] + "\033[0m" + ") ... "
         )
 
-        peer = Network(peer_id, **args)
+        _registered_peer = Network(peer_id, **args)
 
         sys.stdout.write("\033[92m" + "OK" + "\033[0m" + "\n")
         sys.stdout.write("Peer ID: " + peer_id + "\n")
@@ -45,8 +57,11 @@ def register(**kwargs):
         sys.stdout.write(
             " - Want to join in our development team? Apply here: https://forms.gle/wcH1vxzvPyDSbSVW6\n"
         )
-        peer.start()
-        return peer
+
+        _registered_peer.start()
+
+        return _registered_peer
+
     except Exception as e:
         sys.stdout.write("\033[91m" + "FAIL" + "\033[0m" + "\n")
         sys.stdout.write("You were not able to register your node.\n")


Test patch:
Repository: OpenMined/PySyft

Issue:
FV cipher-text data change during decryption.
## Description
During the decryption process, the ciphertext was soft copied and it changed the ciphertext value during decryption. So we lose the value of ciphertext.
## How to Reproduce
1. Create a ciphertext
2. Decrypt that ciphertext
3. Retry to decrypt the same ciphertext (wrong result)



Discussion:

Resolving patch:
diff --git a/syft/frameworks/torch/he/fv/decryptor.py b/syft/frameworks/torch/he/fv/decryptor.py
--- a/syft/frameworks/torch/he/fv/decryptor.py
+++ b/syft/frameworks/torch/he/fv/decryptor.py
@@ -1,3 +1,4 @@
+import copy
 from numpy.polynomial import polynomial as poly
 
 
@@ -32,7 +33,7 @@ def decrypt(self, encrypted):
         """
 
         # Calculate [c0 + c1 * sk + c2 * sk^2 ...]_q
-        temp_product_modq = self._mul_ct_sk(encrypted.data)
+        temp_product_modq = self._mul_ct_sk(copy.deepcopy(encrypted.data))
 
         # Divide scaling variant using BEHZ FullRNS techniques
         result = self._context.rns_tool.decrypt_scale_and_round(temp_product_modq)


Test patch:
diff --git a/test/torch/tensors/test_fv.py b/test/torch/tensors/test_fv.py
--- a/test/torch/tensors/test_fv.py
+++ b/test/torch/tensors/test_fv.py
@@ -356,3 +356,20 @@ def test_fv_encryption_decrption_standard_seq_level(
     encryptor = Encryptor(ctx, keys[1])  # keys[1] = public_key
     decryptor = Decryptor(ctx, keys[0])  # keys[0] = secret_key
     assert integer == encoder.decode(decryptor.decrypt(encryptor.encrypt(encoder.encode(integer))))
+
+
+def test_fv_encryption_decrption_without_changing_parameters():
+    ctx = Context(EncryptionParams(1024, CoeffModulus().create(1024, [30, 30]), 1024))
+    keys = KeyGenerator(ctx).keygen()
+    encoder = IntegerEncoder(ctx)
+    encryptor = Encryptor(ctx, keys[1])  # keys[1] = public_key
+    decryptor = Decryptor(ctx, keys[0])  # keys[0] = secret_key
+    values = [0, 1, -1, 100, -100, 1000]
+    for value in values:
+        # Checking simple encryption-decryption with same parameters.
+        assert value == encoder.decode(decryptor.decrypt(encryptor.encrypt(encoder.encode(value))))
+
+        # Checking the decryption of same ciphertext 3 times (checking for ciphertext deepcopy).
+        ct = encryptor.encrypt(encoder.encode(value))
+        for _ in range(3):
+            assert value == encoder.decode(decryptor.decrypt(ct))
Repository: OpenMined/PySyft

Issue:
Update Polynomial operations for non same size polynomials.
## Description
Fix poly_mul_mod operations for two non-same size polynomial arguments.
polynomial operations are done with wrong orientation.

## How to Reproduce
1. Apply `poly_mul_mod` with two non-same size polynomials.
2. The result is incorrect.



Discussion:

Resolving patch:
diff --git a/syft/frameworks/torch/he/fv/util/operations.py b/syft/frameworks/torch/he/fv/util/operations.py
--- a/syft/frameworks/torch/he/fv/util/operations.py
+++ b/syft/frameworks/torch/he/fv/util/operations.py
@@ -66,6 +66,15 @@ def poly_add_mod(op1, op2, modulus):
 def poly_mul_mod(op1, op2, modulus):
     """return multiplication of two polynomials with all coefficients of
     polynomial %q(coefficient modulus) and result polynomial % t(polynomial modulus)"""
+
+    # For non same size polynomails we have to shift the polynomials because numpy consider right
+    # side as lower order of polynomial and we consider right side as heigher order.
+    if len(op1) != len(op2):
+        if len(op1) > len(op2):
+            op2 = op2 + [0] * (len(op1) - len(op2))
+        else:
+            op1 = op1 + [0] * (len(op2) - len(op1))
+
     poly_mod = np.array([1] + [0] * (len(op1) - 1) + [1])
     result = (
         poly.polydiv(


Test patch:
diff --git a/test/torch/tensors/test_fv.py b/test/torch/tensors/test_fv.py
--- a/test/torch/tensors/test_fv.py
+++ b/test/torch/tensors/test_fv.py
@@ -125,6 +125,8 @@ def test_CoeffModulus_bfv_default(poly_modulus, SeqLevelType, result):
         ([0, 0], [0, 0], 3, [0, 0]),
         ([1, 2, 3, 4], [2, 3, 4, 5], 3, [0, 2, 1, 0]),
         ([1, 2, 3, 4], [2, 3, 4, 5], 1, [0, 0, 0, 0]),
+        ([1, 2, 3, 4, 5], [1, -4], 3, [1, 2, 0, 2, 1]),
+        ([4, 4], [-4, -4, -4, -4], 4, [0, 0, 0, 0]),
     ],
 )
 def test_poly_add_mod(op1, op2, mod, result):
@@ -133,7 +135,12 @@ def test_poly_add_mod(op1, op2, mod, result):
 
 @pytest.mark.parametrize(
     "op1, op2, mod, result",
-    [([1, 1], [2, 1], 5, [1, 3]), ([1, 2, 3, 4], [2, 3, 4, 5], 5, [3, 1, 1])],
+    [
+        ([1, 1], [2, 1], 5, [1, 3]),
+        ([1, 2, 3, 4], [2, 3, 4, 5], 5, [3, 1, 1]),
+        ([1, 2, 3, 4, 5], [1, -4], 3, [0, 1, 1, 1, 1]),
+        ([4, 4], [-4, -4, -4, -4], 4, [0]),
+    ],
 )
 def test_poly_mul_mod(op1, op2, mod, result):
     print("test poly_mul_mod : ", poly_mul_mod(op1, op2, mod))
Repository: OpenMined/PySyft

Issue:
Implement Negation operation for FV HE Scheme
## Feature Description
Negation operations of FV Scheme need to be implemented.

It should Negate a ciphertext object and return the result in ciphertext form.


Discussion:

Resolving patch:
diff --git a/syft/frameworks/torch/he/fv/evaluator.py b/syft/frameworks/torch/he/fv/evaluator.py
--- a/syft/frameworks/torch/he/fv/evaluator.py
+++ b/syft/frameworks/torch/he/fv/evaluator.py
@@ -1,6 +1,7 @@
 import copy
 
 from syft.frameworks.torch.he.fv.util.operations import poly_add_mod
+from syft.frameworks.torch.he.fv.util.operations import negate_mod
 from syft.frameworks.torch.he.fv.util.operations import multiply_add_plain_with_delta
 from syft.frameworks.torch.he.fv.ciphertext import CipherText
 from syft.frameworks.torch.he.fv.plaintext import PlainText
@@ -39,6 +40,24 @@ def add(self, op1, op2):
         else:
             raise TypeError(f"Addition Operation not supported between {type(op1)} and {type(op2)}")
 
+    def negate(self, ct):
+        """Negate a cipher i.e -(ct_value)
+
+        Args:
+            ct (Ciphertext): Ciphertext to be negated.
+
+        Returns:
+            A Ciphertext object with value equivalent to result of -(ct_value).
+        """
+        result = copy.deepcopy(ct.data)
+
+        for i in range(len(result)):
+            for j in range(len(result[i])):
+                for k in range(len(result[i][j])):
+                    result[i][j][k] = negate_mod(ct.data[i][j][k], self.coeff_modulus[j])
+
+        return CipherText(result)
+
     def _add_cipher_cipher(self, ct1, ct2):
         """Adds two ciphertexts.
 


Test patch:
diff --git a/test/torch/tensors/test_fv.py b/test/torch/tensors/test_fv.py
--- a/test/torch/tensors/test_fv.py
+++ b/test/torch/tensors/test_fv.py
@@ -441,3 +441,15 @@ def test_fv_add_plain_plain(int1, int2):
         == encoder.decode(evaluator.add(op1, op2))
         == encoder.decode(evaluator.add(op2, op1))
     )
+
+
+@pytest.mark.parametrize("val", [(0), (-1), (100), (-1000), (-123), (99), (0xFFF), (0xFFFFFF)])
+def test_fv_negate_cipher(val):
+    ctx = Context(EncryptionParams(1024, CoeffModulus().create(1024, [30, 30]), 1024))
+    keys = KeyGenerator(ctx).keygen()
+    encoder = IntegerEncoder(ctx)
+    evaluator = Evaluator(ctx)
+    encryptor = Encryptor(ctx, keys[1])  # keys[1] = public_key
+    decryptor = Decryptor(ctx, keys[0])  # keys[0] = secret_key
+    op = encryptor.encrypt(encoder.encode(val))
+    assert -val == encoder.decode(decryptor.decrypt(evaluator.negate(op)))
Repository: OpenMined/PySyft

Issue:
Return invalid dtype when MPC is applied to Other Dtype Tensor
## Description

When MPC is applied to the int tensor, it must be int but float return.

## How to Reproduce

```python
x = torch.tensor([1, 2, 3])
print(x.dtype) # torch.int64

x = share(bob, alice, crypto_provider=theo)
print(x.dtype) # torch.float32 # should be torch.int64

print(x.get().dtype) # torch.int64
```

## Expected Behavior

should be `torch.int64`

## Screenshots

![image](https://user-images.githubusercontent.com/39186433/89849067-a9f89380-dbc2-11ea-84aa-6bf791a46b78.png)


## System Information
 - OS: MAC
 - OS Version: Catalina
 - Language Version: Python3.7
 - Package Manager Version: Conda 4.8.3
 - Browser (if applicable): [e.g. Google Chrome]
 - Browser Version (if applicable): [e.g. 81.0.4044.138]

## Additional Context





Discussion:

Resolving patch:
diff --git a/syft/frameworks/torch/tensors/interpreters/native.py b/syft/frameworks/torch/tensors/interpreters/native.py
--- a/syft/frameworks/torch/tensors/interpreters/native.py
+++ b/syft/frameworks/torch/tensors/interpreters/native.py
@@ -945,7 +945,7 @@ def share(
             shared_tensor = syft.AutogradTensor().on(shared_tensor, wrap=False)
 
         if not no_wrap:
-            shared_tensor = shared_tensor.wrap()
+            shared_tensor = shared_tensor.wrap(type=self.dtype)
 
         return shared_tensor
 


Test patch:
diff --git a/test/torch/tensors/test_additive_shared.py b/test/torch/tensors/test_additive_shared.py
--- a/test/torch/tensors/test_additive_shared.py
+++ b/test/torch/tensors/test_additive_shared.py
@@ -41,6 +41,7 @@ def test_share_get(workers, protocol, dtype, n_workers):
 
     t = torch.tensor([1, 2, 3])
     x = t.share(*share_holders[:n_workers], **kwargs)
+    assert t.dtype == x.dtype
     x = x.get()
 
     assert (x == t).all()
Repository: OpenMined/PySyft

Issue:
Flaky exp test
## Description
The tolerance for the ```exp``` needs to be increased since it is failing randomly (because of the random order in which we run the tests).

## How to Reproduce
```
____________________ test_torch_sigmoid_approx[exp-3-0.065] ____________________

method = 'exp', prec_frac = 3, tolerance = 0.065
workers = {'alice': <VirtualWorker id:alice #objects:1>, 'bob': <VirtualWorker id:bob #objects:1>, 'charlie': <VirtualWorker id:charlie #objects:0>, 'james': <VirtualWorker id:james #objects:0>, ...}

    @pytest.mark.parametrize(
        "method, prec_frac, tolerance",
        [
            ("chebyshev", 3, 6 / 100),
            ("chebyshev", 4, 1 / 1000),
            ("exp", 3, 6.5 / 100),
            ("exp", 4, 1 / 100),
            ("maclaurin", 3, 7 / 100),
            ("maclaurin", 4, 15 / 100),
        ],
    )
    def test_torch_sigmoid_approx(method, prec_frac, tolerance, workers):
        """
        Test the approximate sigmoid with different tolerance depending on
        the precision_fractional considered
        """
        alice, bob, james = workers["alice"], workers["bob"], workers["james"]
        t = torch.tensor(range(-10, 10)) * 0.5
        t_sh = t.fix_precision(precision_fractional=prec_frac).share(alice, bob, crypto_provider=james)
        r_sh = t_sh.sigmoid(method=method)
        r = r_sh.get().float_prec()
        t = t.sigmoid()
        diff = (r - t).abs().max()
        norm = (r + t).abs().max() / 2
    
>       assert (diff / (tolerance * norm)) < 1
E       assert (tensor(1.2798e+13) / (0.065 * tensor(6.3991e+12))) < 1
```

## Expected Behavior
The test should be passing

## Screenshots
If applicable, add screenshots to help explain your problem.



Discussion:
Hey @gmuraru would want to work on this!
Assigned it to you! But I think this will require more research since it seems that the value is pretty high and probably we do something behind the scenes which brokes the ```exp```. A simple increase in the tolerance would not do the job.

Resolving patch:
diff --git a/syft/frameworks/torch/tensors/interpreters/precision.py b/syft/frameworks/torch/tensors/interpreters/precision.py
--- a/syft/frameworks/torch/tensors/interpreters/precision.py
+++ b/syft/frameworks/torch/tensors/interpreters/precision.py
@@ -559,7 +559,7 @@ def _sigmoid_exp(tensor):
         x = tensor * sign
         ones = tensor * 0 + 1
         half = ones.div(2)
-        result = (ones + (-ones * x).exp()).reciprocal()
+        result = (ones + (-ones * x).exp()).reciprocal(method="division")
         return (result - half) * sign + half
 
     @staticmethod


Test patch: