def test_przs_generate_random_share(get_clients): """Test przs_generate_random_share method from Session.""" session = Session() SessionManager.setup_mpc(session) gen1 = get_new_generator(42) gen2 = get_new_generator(43) generators = [gen1, gen2] share = session.przs_generate_random_share(shape=(2, 1), generators=generators) assert isinstance(share, ShareTensor) target_tensor = torch.tensor( ([-1540733531777602634], [2813554787685566880])) assert (share.tensor == target_tensor).all()
def test_cat(get_clients): clients = get_clients(2) x_secret = torch.Tensor([0.0, 1, -2, 3, -4]) y_secret = torch.Tensor([-4, 3, -2, 1, 0.0]) secret_concatenated = torch.cat([x_secret, y_secret]) session = Session(parties=clients) SessionManager.setup_mpc(session) x = MPCTensor(secret=x_secret, session=session) y = MPCTensor(secret=y_secret, session=session) concatenated = cat([x, y]) assert (secret_concatenated == concatenated.reconstruct()).all()
def test_argmax_dim(dim, keepdim, get_clients) -> None: clients = get_clients(2) session = Session(parties=clients) SessionManager.setup_mpc(session) secret = torch.Tensor([[[1, 2], [3, -1], [4, 5]], [[2, 5], [5, 1], [6, 42]]]) x = MPCTensor(secret=secret, session=session) argmax_val = x.argmax(dim=dim, keepdim=keepdim) assert isinstance(x, MPCTensor), "Expected argmax to be MPCTensor" res = argmax_val.reconstruct() expected = secret.argmax(dim=dim, keepdim=keepdim).float() assert (res == expected).all(), f"Expected argmax to be {expected}"
def test_generate_shares_session(get_clients) -> None: clients = get_clients(2) session = Session(parties=clients) SessionManager.setup_mpc(session) x_secret = torch.Tensor([5.0]) x_share = ShareTensor(data=x_secret, session=session) shares_from_share_tensor = MPCTensor.generate_shares(x_share, 2) shares_from_secret = MPCTensor.generate_shares(x_secret, 2, session=session) assert sum(shares_from_share_tensor) == sum(shares_from_secret)
def test_invalid_malicious_reconstruction(get_clients, parties): parties = get_clients(parties) protocol = Falcon("malicious") session = Session(protocol=protocol, parties=parties) SessionManager.setup_mpc(session) secret = torch.Tensor([[1, -2.0, 0.0], [3.9, -4.394, -0.9], [-43, 100, -0.4343], [1.344, -5.0, 0.55]]) tensor = MPCTensor(secret=secret, session=session) tensor.share_ptrs[0][0] = tensor.share_ptrs[0][0] + 4 with pytest.raises(ValueError): tensor.reconstruct()
def test_mul_private_exception_nothreeparties(get_clients, parties): parties = get_clients(parties) protocol = Falcon("semi-honest") session = Session(protocol=protocol, parties=parties) SessionManager.setup_mpc(session) secret1 = torch.tensor([[-100, 20, 30], [-90, 1000, 1], [1032, -323, 15]]) secret2 = 8 tensor1 = MPCTensor(secret=secret1, session=session) tensor2 = MPCTensor(secret=secret2, session=session) with pytest.raises(ValueError): tensor1 * tensor2
def test_hook_property(get_clients) -> None: clients = get_clients(3) session = Session(parties=clients) SessionManager.setup_mpc(session) x = torch.randn(1, 3) y = torch.randn(1, 3) shares = [x, y] rst = ReplicatedSharedTensor() rst.shares = shares assert (rst.T.shares[0] == x.T).all() assert (rst.T.shares[1] == y.T).all()
def test_comp_public_mpc(get_clients, protocol, op_str) -> None: clients = get_clients(2) session = Session(parties=clients, protocol=protocol) SessionManager.setup_mpc(session) op = getattr(operator, op_str) x_secret = 2.5 y_secret = torch.Tensor([[0.125, -2.5], [-4.25, 2.25]]) y = MPCTensor(secret=y_secret, session=session) result = op(x_secret, y).reconstruct() expected_result = op(x_secret, y_secret) assert (result == expected_result).all()
def test_log_softmax(get_clients, dim) -> None: clients = get_clients(2) x_secret = torch.arange(-6, 6, dtype=torch.float).view(3, 4) x_secret_log_softmax = F.log_softmax(x_secret, dim=dim) session = Session(parties=clients) SessionManager.setup_mpc(session) x = MPCTensor(secret=x_secret, session=session) x_log_softmax = log_softmax(x, dim=dim) assert torch.allclose(x_secret_log_softmax, x_log_softmax.reconstruct(), atol=1e-2)
def test_log_softmax_single_along_dim(get_clients) -> None: clients = get_clients(2) x_secret = torch.arange(4, dtype=torch.float).view(4, 1) x_secret_log_softmax = F.log_softmax(x_secret) session = Session(parties=clients) SessionManager.setup_mpc(session) x = MPCTensor(secret=x_secret, session=session) x_log_softmax = log_softmax(x) assert torch.allclose(x_secret_log_softmax, x_log_softmax.reconstruct(), atol=1e-2)
def test_reciprocal(method, get_clients) -> None: clients = get_clients(2) session_one = Session(parties=clients) SessionManager.setup_mpc(session_one) x_secret = torch.Tensor([-2.0, 6.0, 2.0, 3.0, -5.0, -0.5]) x = MPCTensor(secret=x_secret, session=session_one) x_secret_reciprocal = torch.reciprocal(x_secret) x_reciprocal = reciprocal(x, method=method) assert torch.allclose(x_secret_reciprocal, x_reciprocal.reconstruct(), atol=1e-1)
def test_primitive_logging_model(get_clients) -> None: model = LinearNet(torch) clients = get_clients(2) session = Session(parties=clients) SessionManager.setup_mpc(session) mpc_model = model.share(session=session) x_secret = torch.randn(2, 3) x_mpc = MPCTensor(secret=x_secret, session=session) model.eval() expected_primitive_log = { "beaver_matmul": [( { "a_shape": (2, 3), "b_shape": (3, 10) }, { "session": session, "a_shape": (2, 3), "b_shape": (3, 10), "nr_parties": 2, }, )], "fss_comp": [({}, { "n_values": 20 })], "beaver_mul": [( { "a_shape": (2, 10), "b_shape": (2, 10) }, { "session": session, "a_shape": (2, 10), "b_shape": (2, 10), "nr_parties": 2, }, )], } CryptoPrimitiveProvider.start_logging() mpc_model(x_mpc) primitive_log = CryptoPrimitiveProvider.stop_logging() assert expected_primitive_log == primitive_log
def test_log(get_clients) -> None: clients = get_clients(2) x_secret = torch.Tensor([0.1, 0.5, 2, 5, 10]) x_secret_log = torch.log(x_secret) # with custom precision config = Config(encoder_precision=20) session = Session(parties=clients, config=config) SessionManager.setup_mpc(session) x = MPCTensor(secret=x_secret, session=session) x_log = log(x) assert torch.allclose(x_secret_log, x_log.reconstruct(), atol=1e-1)
def test_sort_invalidim_exception(get_clients): clients = get_clients(2) session = Session(parties=clients) SessionManager.setup_mpc(session) x = MPCTensor(secret=torch.tensor([1]), session=session) y = MPCTensor(secret=torch.tensor([3]), session=session) z = MPCTensor(secret=torch.tensor([6, 2]), session=session) mpctensor_list = [x, y, z] with pytest.raises(ValueError): sort(mpctensor_list)
def test_max(get_clients) -> None: clients = get_clients(2) session = Session(parties=clients) SessionManager.setup_mpc(session) secret = torch.Tensor([1, 2, 3, -1, -3]) x = MPCTensor(secret=secret, session=session) max_val = x.max() assert isinstance(x, MPCTensor), "Expected argmax to be MPCTensor" expected = secret.max() res = max_val.reconstruct() assert res == expected, f"Expected argmax to be {expected}"
def test_ops_public_mul_matrix(get_clients, security, base, precision): parties = get_clients(3) protocol = Falcon(security) config = Config(encoder_base=base, encoder_precision=precision) session = Session(protocol=protocol, parties=parties, config=config) SessionManager.setup_mpc(session) secret = torch.Tensor([[0.125, 1001, 4.82, -1.25], [-4.25, 0.217, 3301, 4]]) value = torch.Tensor([[4.5, 9.25, 3.47, -2.5], [50, 3.17, 5.82, 2.25]]) tensor = MPCTensor(secret=secret, session=session) result = tensor * value expected_res = secret * value assert np.allclose(result.reconstruct(), expected_res, atol=1e-3)
def test_private_compare_exception(get_clients) -> None: parties = get_clients(3) falcon = Falcon() session = Session(parties=parties, protocol=falcon) SessionManager.setup_mpc(session) x = MPCTensor(secret=1, session=session) r = torch.tensor([1]) # Expection for not passing input tensor values as list. with pytest.raises(ValueError): Falcon.private_compare(x, r) # Exception for not passing a public value(torch.Tensor). with pytest.raises(ValueError): Falcon.private_compare([x], x)
def test_bin_public_xor(get_clients, bit) -> None: clients = get_clients(3) falcon = Protocol.registered_protocols["Falcon"]() session = Session(parties=clients, protocol=falcon) session.config = Config(encoder_base=1, encoder_precision=0) SessionManager.setup_mpc(session) x = torch.tensor([[1, 0], [0, 1]], dtype=torch.bool) b = torch.tensor([bit], dtype=torch.bool) x_share = MPCTensor(secret=x, session=session) result = operator.xor(x_share, b) expected_res = x ^ b assert (result.reconstruct() == expected_res).all()
def test_send_get(get_clients, precision=12, base=4) -> None: client = get_clients(1)[0] protocol = Falcon("semi-honest") session = Session(protocol=protocol, parties=[client]) SessionManager.setup_mpc(session) share1 = torch.Tensor([1.4, 2.34, 3.43]) share2 = torch.Tensor([1, 2, 3]) share3 = torch.Tensor([1.4, 2.34, 3.43]) session_uuid = session.rank_to_uuid[0] x_share = ReplicatedSharedTensor(shares=[share1, share2, share3], session_uuid=session_uuid) x_ptr = x_share.send(client) result = x_ptr.get() assert result == x_share
def test_tanh(get_clients) -> None: clients = get_clients(2) x_secret = torch.Tensor([0.0, 1, -2, 3, -4]) x_secret_tanh = torch.tanh(x_secret) session = Session(parties=clients) SessionManager.setup_mpc(session) x = MPCTensor(secret=x_secret, session=session) x_tanh = tanh(x, method="sigmoid") assert torch.allclose(x_secret_tanh, x_tanh.reconstruct(), atol=1e-2) with pytest.raises(ValueError): x_tanh = tanh(x, method="exp")
def test_mse_loss(get_clients) -> None: clients = get_clients(4) session = Session(parties=clients) SessionManager.setup_mpc(session) y_secret = torch.Tensor([0.23, 0.32, 0.2, 0.3]) y_mpc = MPCTensor(secret=y_secret, session=session) y_pred = torch.Tensor([0.1, 0.3, 0.4, 0.2]) y_pred_mpc = MPCTensor(secret=y_pred, session=session) res = mse_loss(y_mpc, y_pred_mpc) res_expected = torch.nn.functional.mse_loss(y_secret, y_pred, reduction="sum") assert np.allclose(res.reconstruct(), res_expected, atol=1e-4)
def test_pow(get_clients, power) -> None: clients = get_clients(2) session = Session(parties=clients) SessionManager.setup_mpc(session) x_secret = torch.Tensor([5.0, -3]) x = MPCTensor(secret=x_secret, session=session) power_secret = x_secret**power power = x**power assert torch.allclose(power_secret, power.reconstruct()) with pytest.raises(RuntimeError): power = x**-2
def test_ops_public_mpc(get_clients, nr_clients, op_str) -> None: clients = get_clients(nr_clients) session = Session(parties=clients) SessionManager.setup_mpc(session) op = getattr(operator, op_str) x_secret = torch.Tensor([[0.125, -1.25], [-4.25, 4]]) y_secret = torch.Tensor([[4.5, -2.5], [5, 2.25]]) x = MPCTensor(secret=x_secret, session=session) expected_result = op(y_secret, x_secret) result = op(y_secret, x).reconstruct() assert np.allclose(result, expected_result, atol=10e-4)
def test_reconstruct(get_clients) -> None: clients = get_clients(2) session = Session(parties=clients) SessionManager.setup_mpc(session) a_rand = 3 a = ShareTensor(data=a_rand, encoder_precision=0) a_shares = MPCTensor.generate_shares(a, 2, torch.long) a_shares_copy = MPCTensor.generate_shares(a_rand, 2, torch.long) x_secret = torch.Tensor([1, -2, 3.0907, -4.870]) x = MPCTensor(secret=x_secret, session=session) x = x.reconstruct() assert torch.allclose(x_secret, x)
def test_ops_mpc_private_rst(get_clients, nr_clients, op_str) -> None: clients = get_clients(nr_clients) falcon = Protocol.registered_protocols["Falcon"]() session = Session(parties=clients, protocol=falcon) SessionManager.setup_mpc(session) op = getattr(operator, op_str) x_secret = torch.Tensor([[0.125, -1.25], [-4.25, 4]]) y_secret = torch.Tensor([[4.5, -2.5], [5, 2.25]]) x = MPCTensor(secret=x_secret, session=session) y = MPCTensor(secret=y_secret, session=session) expected_result = op(x_secret, y_secret) result = op(x, y).reconstruct() assert np.allclose(result, expected_result, atol=10e-4)
def test_remote_not_tensor(get_clients) -> None: alice_client, bob_client = get_clients(2) session = Session(parties=[alice_client, bob_client]) SessionManager.setup_mpc(session) x_remote_int = bob_client.python.Int(5) x = MPCTensor(secret=x_remote_int, shape=(1, ), session=session) result = x.reconstruct() assert x_remote_int == result x_remote_int = bob_client.python.Float(5.4) x = MPCTensor(secret=x_remote_int, shape=(1, ), session=session) result = x.reconstruct() assert np.allclose(x_remote_int.get(), result, atol=1e-5)
def test_private_matmul(get_clients, security): parties = get_clients(3) protocol = Falcon(security) session = Session(protocol=protocol, parties=parties) SessionManager.setup_mpc(session) secret1 = torch.tensor([ [[-100.25, 20.3, 30.12], [-50.1, 100.217, 1.2], [1032.15, -323.56, 15.15]], [[-0.25, 2.3, 3012], [-5.01, 1.00217, 1.2], [2.15, -3.56, 15.15]], ]) secret2 = torch.tensor([[-1, 0.28, 3], [-9, 10.18, 1], [32, -23, 5]]) tensor1 = MPCTensor(secret=secret1, session=session) tensor2 = MPCTensor(secret=secret2, session=session) result = tensor1 @ tensor2 expected_res = secret1 @ secret2 assert np.allclose(result.reconstruct(), expected_res, atol=1e-3)
def test_ops_integer(get_clients, nr_clients, op_str) -> None: clients = get_clients(nr_clients) session = Session(parties=clients) SessionManager.setup_mpc(session) op = getattr(operator, op_str) x_secret = torch.Tensor([0.125, -1.25, -4.25, 4]) y = 4 x = MPCTensor(secret=x_secret, session=session) expected_result = op(x_secret, y) result = op(x, y).reconstruct() assert np.allclose(result, expected_result, atol=10e-3)
def test_local_secret_not_tensor(get_clients) -> None: alice_client, bob_client = get_clients(2) session = Session(parties=[alice_client, bob_client]) SessionManager.setup_mpc(session) x_int = 5 x = MPCTensor(secret=x_int, session=session) result = x.reconstruct() assert x_int == result x_float = 5.987 x = MPCTensor(secret=x_float, session=session) result = x.reconstruct() assert np.allclose(torch.tensor(x_float), result)
def test_max_pool2d_raises_value_error_kernel_gt_input(get_clients) -> None: clients = get_clients(2) session = Session(parties=clients) SessionManager.setup_mpc(session) secret = torch.Tensor([[[0.23]]]) mpc = MPCTensor(secret=secret, session=session) with pytest.raises(ValueError): sympc.module.nn.max_pool2d(mpc, kernel_size=5, stride=1, padding=1) with pytest.raises(ValueError): sympc.module.nn.max_pool2d(mpc, kernel_size=2, stride=1, padding=0, return_indices=True)