Skip to content

Commit

Permalink
Check for empty vectors upon encryption (OpenMined#126)
Browse files Browse the repository at this point in the history
* Simple checker

* add stdexcept library

* added in test cases asserting that a runtime error is thrown

* Tests passing and failing exception cases as expected

* separated test for empty vector

* formatting

* handle lint

* added changes across various tests

Co-authored-by: Ayoub Benaissa <[email protected]>
  • Loading branch information
IanQS and youben11 authored Aug 3, 2020
1 parent 502a920 commit 1b957e5
Show file tree
Hide file tree
Showing 9 changed files with 87 additions and 61 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@
# VSCODE
.vscode/

# Jetbrains tools
.idea/

## Python

# Byte-compiled / optimized / DLL files
Expand All @@ -49,6 +52,7 @@ __pycache__/
# Distribution / packaging
.Python
build/
cmake-build-debug
develop-eggs/
dist/
downloads/
Expand Down
4 changes: 4 additions & 0 deletions tenseal/cpp/tensors/bfvvector.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define TENSEAL_TENSOR_BFVVECTOR_H

#include <memory>
#include <stdexcept>
#include <vector>

#include "seal/seal.h"
Expand Down Expand Up @@ -101,6 +102,9 @@ class BFVVector {

static Ciphertext encrypt(shared_ptr<TenSEALContext> context,
vector<int64_t> pt) {
if (pt.empty()) {
throw invalid_argument("Attempting to encrypt an empty vector");
}
Ciphertext ciphertext(context->seal_context());
Plaintext plaintext;
context->encode<BatchEncoder>(pt, plaintext);
Expand Down
4 changes: 4 additions & 0 deletions tenseal/cpp/tensors/ckksvector.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include <memory>
#include <optional>
#include <stdexcept>
#include <vector>

#include "seal/seal.h"
Expand Down Expand Up @@ -174,6 +175,9 @@ class CKKSVector {

static Ciphertext encrypt(shared_ptr<TenSEALContext> context, double scale,
vector<double> pt) {
if (pt.empty()) {
throw invalid_argument("Attempting to encrypt an empty vector");
}
auto slot_count = context->slot_count<CKKSEncoder>();
if (pt.size() > slot_count)
// number of slots available is poly_modulus_degree / 2
Expand Down
9 changes: 9 additions & 0 deletions tests/cpp/tensors/bfvvector_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,15 @@ TEST_P(BFVVectorTest, TestBFVMul) {
EXPECT_THAT(decr, ElementsAreArray({16, 32, 48}));
}

TEST_P(BFVVectorTest, TestEmptyPlaintext) {

auto ctx = TenSEALContext::Create(scheme_type::BFV, 8192, 1032193, {});
ASSERT_TRUE(ctx != nullptr);

EXPECT_THROW(BFVVector(ctx, std::vector<int64_t>({})), std::exception);
}


INSTANTIATE_TEST_CASE_P(TestBFVVector, BFVVectorTest,
::testing::Values(false, true));

Expand Down
8 changes: 8 additions & 0 deletions tests/cpp/tensors/ckksvector_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,14 @@ TEST_P(CKKSVectorTest, TestCKKSPlainMatMul) {
ASSERT_TRUE(are_close(decrypted_result, expected_result));
}


TEST_P(CKKSVectorTest, TestEmptyPlaintext) {
auto ctx = TenSEALContext::Create(scheme_type::BFV, 8192, 1032193, {});
ASSERT_TRUE(ctx != nullptr);

EXPECT_THROW(CKKSVector(ctx, std::vector<double>({})), std::exception);
}

INSTANTIATE_TEST_CASE_P(TestCKKSVector, CKKSVectorTest,
::testing::Values(false, true));

Expand Down
14 changes: 1 addition & 13 deletions tests/python/tenseal/tensors/test_bfv_vector.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ def context():
@pytest.mark.parametrize(
"vec1, vec2",
[
([], []),
([0], [0]),
([1], [0]),
([-1], [0]),
Expand Down Expand Up @@ -42,7 +41,6 @@ def test_add(context, vec1, vec2):
@pytest.mark.parametrize(
"vec1, vec2",
[
([], []),
([0], [0]),
([1], [0]),
([-1], [0]),
Expand Down Expand Up @@ -71,7 +69,6 @@ def test_add_inplace(context, vec1, vec2):
@pytest.mark.parametrize(
"vec1, vec2",
[
([], []),
([0], [0]),
([1], [0]),
([-1], [0]),
Expand Down Expand Up @@ -100,7 +97,6 @@ def test_add_plain(context, vec1, vec2):
@pytest.mark.parametrize(
"vec1, vec2",
[
([], []),
([0], [0]),
([1], [0]),
([-1], [0]),
Expand Down Expand Up @@ -128,7 +124,6 @@ def test_add_plain_inplace(context, vec1, vec2):
@pytest.mark.parametrize(
"vec1, vec2",
[
([], []),
([0], [0]),
([1], [0]),
([-1], [0]),
Expand Down Expand Up @@ -157,7 +152,6 @@ def test_sub(context, vec1, vec2):
@pytest.mark.parametrize(
"vec1, vec2",
[
([], []),
([0], [0]),
([1], [0]),
([-1], [0]),
Expand Down Expand Up @@ -186,7 +180,6 @@ def test_sub_inplace(context, vec1, vec2):
@pytest.mark.parametrize(
"vec1, vec2",
[
([], []),
([0], [0]),
([1], [0]),
([-1], [0]),
Expand Down Expand Up @@ -215,7 +208,6 @@ def test_sub_plain(context, vec1, vec2):
@pytest.mark.parametrize(
"vec1, vec2",
[
([], []),
([0], [0]),
([1], [0]),
([-1], [0]),
Expand All @@ -242,7 +234,6 @@ def test_sub_plain_inplace(context, vec1, vec2):
@pytest.mark.parametrize(
"vec1, vec2",
[
([], []),
([0], [0]),
([1], [0]),
([-1], [0]),
Expand Down Expand Up @@ -272,7 +263,6 @@ def test_mul(context, vec1, vec2):
@pytest.mark.parametrize(
"vec1, vec2",
[
([], []),
([0], [0]),
([1], [0]),
([-1], [0]),
Expand Down Expand Up @@ -301,7 +291,6 @@ def test_mul_inplace(context, vec1, vec2):
@pytest.mark.parametrize(
"vec1, vec2",
[
([], []),
([0], [0]),
([1], [0]),
([-1], [0]),
Expand Down Expand Up @@ -330,7 +319,6 @@ def test_mul_plain(context, vec1, vec2):
@pytest.mark.parametrize(
"vec1, vec2",
[
([], []),
([0], [0]),
([1], [0]),
([-1], [0]),
Expand All @@ -356,6 +344,6 @@ def test_mul_plain_inplace(context, vec1, vec2):


def test_size(context):
for size in range(10):
for size in range(1, 10):
vec = ts.bfv_vector(context, [1] * size)
assert vec.size() == size, "Size of encrypted vector is incorrect."
25 changes: 3 additions & 22 deletions tests/python/tenseal/tensors/test_ckks_vector.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def precision():


@pytest.mark.parametrize(
"plain_vec", [[], [0], [-1], [1], [21, 81, 90], [-73, -81, -90], [-11, 82, -43, 52]]
"plain_vec", [[0], [-1], [1], [21, 81, 90], [-73, -81, -90], [-11, 82, -43, 52]]
)
def test_negate(context, plain_vec, precision):
ckks_vec = ts.ckks_vector(context, plain_vec)
Expand All @@ -54,7 +54,7 @@ def test_negate(context, plain_vec, precision):


@pytest.mark.parametrize(
"plain_vec", [[], [0], [-1], [1], [21, 81, 90], [-73, -81, -90], [-11, 82, -43, 52]]
"plain_vec", [[0], [-1], [1], [21, 81, 90], [-73, -81, -90], [-11, 82, -43, 52]]
)
def test_negate_inplace(context, plain_vec, precision):
ckks_vec = ts.ckks_vector(context, plain_vec)
Expand All @@ -68,7 +68,6 @@ def test_negate_inplace(context, plain_vec, precision):
@pytest.mark.parametrize(
"plain_vec, power, precision",
[
([], 2, 1),
([0], 3, 1),
([0, 1, -1, 2, -2], 0, 1),
([1, -1, 2, -2], 1, 1),
Expand Down Expand Up @@ -102,7 +101,6 @@ def test_power(context, plain_vec, power, precision):
@pytest.mark.parametrize(
"plain_vec, power, precision",
[
([], 2, 1),
([0], 3, 1),
([0, 1, -1, 2, -2], 0, 1),
([1, -1, 2, -2], 1, 1),
Expand Down Expand Up @@ -133,7 +131,6 @@ def test_power_inplace(context, plain_vec, power, precision):
@pytest.mark.parametrize(
"plain_vec",
[
[],
[0],
[1],
[2],
Expand All @@ -160,7 +157,6 @@ def test_square(context, plain_vec, precision):
@pytest.mark.parametrize(
"plain_vec",
[
[],
[0],
[1],
[2],
Expand All @@ -183,7 +179,6 @@ def test_square_inplace(context, plain_vec, precision):
@pytest.mark.parametrize(
"vec1, vec2",
[
([], []),
([0], [0]),
([1], [0]),
([-1], [0]),
Expand Down Expand Up @@ -223,7 +218,6 @@ def test_add(context, vec1, vec2, precision):
@pytest.mark.parametrize(
"vec1, vec2",
[
([], []),
([0], [0]),
([1], [0]),
([-1], [0]),
Expand Down Expand Up @@ -261,7 +255,6 @@ def test_add_inplace(context, vec1, vec2, precision):
@pytest.mark.parametrize(
"vec1, vec2",
[
([], []),
([0], [0]),
([1], [0]),
([-1], [0]),
Expand Down Expand Up @@ -294,7 +287,6 @@ def test_add_plain(context, vec1, vec2, precision):
@pytest.mark.parametrize(
"vec1, vec2",
[
([], []),
([0], [0]),
([1], [0]),
([-1], [0]),
Expand Down Expand Up @@ -326,7 +318,6 @@ def test_radd_plain(context, vec1, vec2, precision):
@pytest.mark.parametrize(
"vec1, vec2",
[
([], []),
([0], [0]),
([1], [0]),
([-1], [0]),
Expand Down Expand Up @@ -358,7 +349,6 @@ def test_add_plain_inplace(context, vec1, vec2, precision):
@pytest.mark.parametrize(
"vec1, vec2",
[
([], []),
([0], [0]),
([1], [0]),
([-1], [0]),
Expand Down Expand Up @@ -399,7 +389,6 @@ def test_sub(context, vec1, vec2, precision):
@pytest.mark.parametrize(
"vec1, vec2",
[
([], []),
([0], [0]),
([1], [0]),
([-1], [0]),
Expand Down Expand Up @@ -439,7 +428,6 @@ def test_sub_inplace(context, vec1, vec2, precision):
@pytest.mark.parametrize(
"vec1, vec2",
[
([], []),
([0], [0]),
([1], [0]),
([-1], [0]),
Expand Down Expand Up @@ -474,7 +462,6 @@ def test_sub_plain(context, vec1, vec2, precision):
@pytest.mark.parametrize(
"vec1, vec2",
[
([], []),
([0], [0]),
([1], [0]),
([-1], [0]),
Expand Down Expand Up @@ -508,7 +495,6 @@ def test_rsub_plain(context, vec1, vec2, precision):
@pytest.mark.parametrize(
"vec1, vec2",
[
([], []),
([0], [0]),
([1], [0]),
([-1], [0]),
Expand Down Expand Up @@ -542,7 +528,6 @@ def test_sub_plain_inplace(context, vec1, vec2, precision):
@pytest.mark.parametrize(
"vec1, vec2",
[
([], []),
([0], [0]),
([1], [0]),
([-1], [0]),
Expand Down Expand Up @@ -583,7 +568,6 @@ def test_mul(context, vec1, vec2, precision):
@pytest.mark.parametrize(
"vec1, vec2",
[
([], []),
([0], [0]),
([1], [0]),
([-1], [0]),
Expand Down Expand Up @@ -623,7 +607,6 @@ def test_mul_inplace(context, vec1, vec2, precision):
@pytest.mark.parametrize(
"vec1, vec2",
[
([], []),
([0], [0]),
([1], [0]),
([-1], [0]),
Expand Down Expand Up @@ -658,7 +641,6 @@ def test_mul_plain(context, vec1, vec2, precision):
@pytest.mark.parametrize(
"vec1, vec2",
[
([], []),
([0], [0]),
([1], [0]),
([-1], [0]),
Expand Down Expand Up @@ -692,7 +674,6 @@ def test_rmul_plain(context, vec1, vec2, precision):
@pytest.mark.parametrize(
"vec1, vec2",
[
([], []),
([0], [0]),
([1], [0]),
([-1], [0]),
Expand Down Expand Up @@ -1197,6 +1178,6 @@ def test_depth_max(poly_mod_degree, coeff_mod_bit_sizes, max_depth):


def test_size(context):
for size in range(10):
for size in range(1, 10):
vec = ts.ckks_vector(context, [1] * size)
assert vec.size() == size, "Size of encrypted vector is incorrect."
Loading

0 comments on commit 1b957e5

Please sign in to comment.