Skip to content

Commit

Permalink
Connect the IR translator to the DP analysis.
Browse files Browse the repository at this point in the history
This change connects the IR translator to the DP analysis. It introduces a new kind of policy object, indicating global limits on DP parameters, and shows this policy being used to cause the analysis to return a pass and a fail on the same IR graph depending upon those parameters.

PiperOrigin-RevId: 468717689
  • Loading branch information
Mark Winterrowd authored and arcs-c3po committed Aug 19, 2022
1 parent 917ebde commit 7b3011c
Show file tree
Hide file tree
Showing 7 changed files with 247 additions and 81 deletions.
19 changes: 19 additions & 0 deletions src/backends/policy_engine/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,22 @@ cc_library(
"//src/ir:module",
],
)

cc_library(
name = "dp_parameter_policy",
hdrs = ["dp_parameter_policy.h"],
deps = [
":policy",
"@absl//absl/strings:str_format",
],
)

cc_test(
name = "dp_parameter_policy_test",
srcs = ["dp_parameter_policy_test.cc"],
deps = [
":dp_parameter_policy",
"//src/common/testing:gtest",
"@absl//absl/strings",
],
)
68 changes: 68 additions & 0 deletions src/backends/policy_engine/dp_parameter_policy.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
//-----------------------------------------------------------------------------
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//----------------------------------------------------------------------------
#ifndef SRC_BACKENDS_POLICY_ENGINE_DP_PARAMETER_POLICY_H_
#define SRC_BACKENDS_POLICY_ENGINE_DP_PARAMETER_POLICY_H_

#include <filesystem>
#include <optional>

#include "absl/strings/str_format.h"
#include "src/backends/policy_engine/policy.h"

namespace raksha::backends::policy_engine {

// A policy where the contents of the policy are just differential privacy
// parameters. For now, we only send over Epsilon and Delta, but we can extend
// this to send more in the future.
class DpParameterPolicy : public Policy {
public:
// Note: The SQL frontend hands us these parameters as floating point
// numbers, so we do eventually want to represent these as `double`s. But
// the IR parser hasn't landed floating point numbers yet, so using
// `uint64_t`s for now.
using DpParameterNumericType = uint64_t;

explicit DpParameterPolicy(DpParameterNumericType epsilon,
DpParameterNumericType delta)
: epsilon_(epsilon), delta_(delta) {}

// Always use the checker compiled from the DP policy verifier interface.
std::string GetPolicyAnalysisCheckerName() const override {
return "dp_policy_verifier_cxx";
}

// This policy always populates the `isDPParameter` relation.
std::optional<std::string> GetPolicyFactName() const override {
return "isDPParameter";
}

std::optional<std::string> GetPolicyString() const override {
return absl::StrFormat(
R"($EpsilonValue(%lu)
$DeltaValue(%lu))",
epsilon_, delta_);
}

private:
// The epsilon differential privacy parameter.
DpParameterNumericType epsilon_;
// The delta differential privacy parameter.
DpParameterNumericType delta_;
};

} // namespace raksha::backends::policy_engine

#endif
56 changes: 0 additions & 56 deletions src/backends/policy_engine/dp_parameter_policy_rule_policy.h

This file was deleted.

90 changes: 90 additions & 0 deletions src/backends/policy_engine/dp_parameter_policy_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#include "src/backends/policy_engine/dp_parameter_policy.h"

#include <optional>

#include "absl/strings/numbers.h"
#include "absl/strings/str_split.h"
#include "src/common/testing/gtest.h"

namespace raksha::backends::policy_engine {
namespace {

using DpParameter = DpParameterPolicy::DpParameterNumericType;
using testing::Combine;
using testing::ValuesIn;

class DpParamaterPolicyRulePolicyTest
: public testing::TestWithParam<std::tuple<DpParameter, DpParameter>> {
protected:
explicit DpParamaterPolicyRulePolicyTest()
: epsilon_(std::get<0>(GetParam())),
delta_(std::get<1>(GetParam())),
policy_(epsilon_, delta_) {}

DpParameter epsilon_;
DpParameter delta_;
DpParameterPolicy policy_;
};

TEST_P(DpParamaterPolicyRulePolicyTest, TestCheckerName) {
EXPECT_EQ(policy_.GetPolicyAnalysisCheckerName(), "dp_policy_verifier_cxx");
}

TEST_P(DpParamaterPolicyRulePolicyTest, TestPolicyFactName) {
std::optional<std::string> policy_fact_name = policy_.GetPolicyFactName();
ASSERT_TRUE(policy_fact_name.has_value());
EXPECT_EQ(*policy_fact_name, "isDPParameter");
}

// Convert a DpParameter to a string, checking our transformation to ensure that
// that string can be perfectly converted back to the input parameter. This may
// seems silly so long as `DpParameter`s are integers, but this will make more
// sense when we switch to floats, as %f and %g will print a fixed-precision
// (and thus possibly lossy) representation (unlike %a).
std::string ConvertParamToStringExpectLossless(DpParameter parameter) {
std::string result = absl::StrFormat("%lu", parameter);
DpParameter parsed_param = 0;
EXPECT_TRUE(absl::SimpleAtoi(result, &parsed_param));
EXPECT_EQ(parsed_param, parameter);
return result;
}

// GetPolicyString constructs a Datalog string from the policy given the
// parameters. Here, we deconstruct that same policy to extract those parameters
// and ensure that they are what we expect.
TEST_P(DpParamaterPolicyRulePolicyTest, TestPolicyString) {
std::optional<std::string> optional_policy_string = policy_.GetPolicyString();
ASSERT_TRUE(optional_policy_string.has_value());
std::string policy_string = *optional_policy_string;
std::vector<std::string> lines =
absl::StrSplit(policy_string, '\n', absl::SkipEmpty());
EXPECT_EQ(lines.size(), 2);

std::string epsilon_value_string =
ConvertParamToStringExpectLossless(epsilon_);
std::string delta_value_string = ConvertParamToStringExpectLossless(delta_);

std::vector<std::string> expected_lines = {
absl::StrFormat("$EpsilonValue(%s)", epsilon_value_string),
absl::StrFormat("$DeltaValue(%s)", delta_value_string)};

EXPECT_THAT(lines, testing::UnorderedElementsAreArray(expected_lines));
}

// Note: some of the parameter values will be duplicated until the DpParameter
// type switches to floating point numbers.
constexpr DpParameter kSampleParameters[] = {
0,
1,
std::numeric_limits<DpParameter>::min(),
std::numeric_limits<DpParameter>::max(),
std::numeric_limits<DpParameter>::lowest(),
std::numeric_limits<DpParameter>::epsilon()};

INSTANTIATE_TEST_SUITE_P(DpParameterPolicyRuleTest,
DpParamaterPolicyRulePolicyTest,
Combine(ValuesIn(kSampleParameters),
ValuesIn(kSampleParameters)));

} // namespace
} // namespace raksha::backends::policy_engine
23 changes: 10 additions & 13 deletions src/backends/policy_engine/souffle/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#----------------------------------------------------------------------------
load(
"//build_defs:raksha_policy_verifier.bzl",
"policy_check",
)

load("//build_defs:package_groups.oss.bzl", "frontend_packages")

package(
Expand All @@ -42,11 +39,6 @@ cc_binary(
],
)

policy_check(
name = "datalog_policy_verifier",
auth_logic_files = ["//src/backends/policy_engine/souffle/testdata:policy.txt"],
)

cc_binary(
name = "check_policy_compliance",
srcs = ["check_policy_compliance.cc"],
Expand Down Expand Up @@ -181,8 +173,9 @@ cc_library(
visibility = ["//src:__subpackages__"] + frontend_packages,
deps = [
":datalog_lowering_visitor",
":datalog_policy_verifier",
":utils",
"//src/analysis/souffle:datalog_policy_verifier_lib",
"//src/analysis/souffle:dp_policy_verifier_lib",
"//src/backends/policy_engine:policy",
"//src/backends/policy_engine:policy_checker",
"//src/common/utils:filesystem",
Expand All @@ -198,16 +191,20 @@ cc_test(
srcs = ["souffle_policy_checker_test.cc"],
deps = [
":souffle_policy_checker",
"//src/backends/policy_engine:policy",
"//src/backends/policy_engine:dp_parameter_policy",
"//src/backends/policy_engine:sql_policy_rule_policy",
"//src/common/logging",
"//src/common/testing:gtest",
"//src/frontends/sql/ops:literal_op",
"//src/frontends/sql/ops:sql_output_op",
"//src/frontends/sql/ops:tag_transform_op",
"//src/ir:block_builder",
"//src/ir:ir_context",
"//src/ir:ir_printer",
"//src/ir:module",
"//src/ir:value",
"//src/ir/attributes:attribute",
"//src/ir/attributes:int_attribute",
"//src/ir/attributes:string_attribute",
"//src/parser/ir:ir_parser",
],
)

Expand Down
Loading

0 comments on commit 7b3011c

Please sign in to comment.