Skip to content

Commit 798d5e4

Browse files
tholopcopybara-github
authored andcommitted
Add C++ utility to generate human-readable Shell parameters from a Willow aggregation config proto; use FfiStatus for interop.
PiperOrigin-RevId: 857168135
1 parent d83bdcb commit 798d5e4

File tree

6 files changed

+245
-3
lines changed

6 files changed

+245
-3
lines changed

shell_wrapper/status_macros.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,9 @@
4949
return status; \
5050
}
5151

52+
// Internal helper to handle results from Rust FFI calls, which return a
53+
// secure_aggregation::FfiStatus instead of a absl::Status.
54+
#define SECAGG_RETURN_IF_FFI_ERROR(expr) \
55+
SECAGG_RETURN_IF_ERROR(secure_aggregation::UnwrapFfiStatus(expr))
56+
5257
#endif // SECURE_AGGREGATION_SHELL_WRAPPER_STATUS_MACROS_H_

willow/src/shell/BUILD

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
load("@cxx.rs//tools/bazel:rust_cxx_bridge.bzl", "rust_cxx_bridge")
16+
load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
1517
load("@rules_rust//rust:defs.bzl", "rust_library", "rust_test")
1618

1719
package(
@@ -113,10 +115,50 @@ rust_library(
113115
crate_root = "parameters_utils.rs",
114116
deps = [
115117
":kahe_shell",
118+
":parameters_shell",
116119
"@protobuf//rust:protobuf",
120+
"@cxx.rs//:cxx",
117121
"//shell_wrapper:kahe",
118122
"//shell_wrapper:status",
119123
"//willow/proto/shell:shell_parameters_rust_proto",
124+
"//willow/proto/willow:aggregation_config_rust_proto",
125+
"//willow/src/api:aggregation_config",
126+
"//willow/src/traits:proto_serialization_traits",
127+
],
128+
)
129+
130+
rust_cxx_bridge(
131+
name = "shell_parameters_utils_cxx",
132+
src = "parameters_utils.rs",
133+
deps = [
134+
":shell_parameters_utils",
135+
"//shell_wrapper:status_cxx",
136+
],
137+
)
138+
139+
cc_library(
140+
name = "shell_parameters_utils_cc",
141+
srcs = ["parameters_utils.cc"],
142+
hdrs = ["parameters_utils.h"],
143+
deps = [
144+
":shell_parameters_utils_cxx",
145+
"@abseil-cpp//absl/status",
146+
"@abseil-cpp//absl/status:statusor",
147+
"@cxx.rs//:core",
148+
"//shell_wrapper:status_cc",
149+
"//shell_wrapper:status_macros",
150+
"//willow/proto/willow:aggregation_config_cc_proto",
151+
],
152+
)
153+
154+
cc_test(
155+
name = "parameters_utils_test",
156+
srcs = ["parameters_utils_test.cc"],
157+
deps = [
158+
":shell_parameters_utils_cc",
159+
"@googletest//:gtest_main",
160+
"@abseil-cpp//absl/status",
161+
"//willow/proto/willow:aggregation_config_cc_proto",
120162
],
121163
)
122164

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Copyright 2026 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "willow/src/shell/parameters_utils.h"
18+
19+
#include <cstdint>
20+
#include <memory>
21+
#include <string>
22+
#include <utility>
23+
24+
#include "absl/status/statusor.h"
25+
#include "include/cxx.h"
26+
#include "shell_wrapper/status_macros.h"
27+
#include "willow/proto/willow/aggregation_config.pb.h"
28+
#include "willow/src/shell/parameters_utils.rs.h"
29+
30+
namespace secure_aggregation {
31+
namespace willow {
32+
33+
absl::StatusOr<std::string> CreateHumanReadableShellConfig(
34+
const AggregationConfigProto& config) {
35+
std::string serialized_config = config.SerializeAsString();
36+
rust::Vec<uint8_t> result;
37+
38+
SECAGG_RETURN_IF_FFI_ERROR(
39+
secure_aggregation::create_human_readable_shell_config(
40+
std::make_unique<std::string>(std::move(serialized_config)),
41+
&result));
42+
43+
return std::string(reinterpret_cast<const char*>(result.data()),
44+
result.size());
45+
}
46+
47+
} // namespace willow
48+
} // namespace secure_aggregation
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright 2026 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#ifndef SECURE_AGGREGATION_WILLOW_SRC_SHELL_PARAMETER_UTILS_H_
18+
#define SECURE_AGGREGATION_WILLOW_SRC_SHELL_PARAMETER_UTILS_H_
19+
20+
#include <string>
21+
22+
#include "absl/status/statusor.h"
23+
#include "willow/proto/willow/aggregation_config.pb.h"
24+
25+
namespace secure_aggregation {
26+
namespace willow {
27+
28+
// Returns the ShellKaheConfig and ShellAheConfig as a human-readable string,
29+
// for the given AggregationConfigProto.
30+
absl::StatusOr<std::string> CreateHumanReadableShellConfig(
31+
const AggregationConfigProto& config);
32+
33+
} // namespace willow
34+
} // namespace secure_aggregation
35+
36+
#endif // SECURE_AGGREGATION_WILLOW_SRC_SHELL_PARAMETER_UTILS_H_

willow/src/shell/parameters_utils.rs

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,67 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
//! This file contains some utility functions for working with Willow parameters:
16+
//! - Conversions between Rust structs and their corresponding protos.
17+
//! - FFI bridge to generate and print Shell parameters from C++.
18+
19+
use aggregation_config::AggregationConfig;
20+
use aggregation_config_rust_proto::AggregationConfigProto;
21+
use cxx::{CxxString, UniquePtr};
1522
use kahe::PackedVectorConfig;
1623
use kahe_shell::ShellKaheConfig;
17-
use protobuf::{proto, ProtoStr};
24+
use parameters_shell::create_shell_configs;
25+
use proto_serialization_traits::FromProto;
26+
use protobuf::{proto, Parse, ProtoStr};
1827
use shell_parameters_rust_proto::{
1928
PackedVectorConfigProto, PackedVectorConfigProtoView, ShellKaheConfigProto,
2029
ShellKaheConfigProtoView,
2130
};
2231
use std::collections::BTreeMap;
2332

24-
/// This file contains some utility functions for working with Willow parameters:
25-
/// - Conversions between Rust structs and their corresponding protos.
33+
#[cxx::bridge]
34+
pub mod ffi {
35+
// Re-define FfiStatus since CXX requires shared structs to be defined in the same module
36+
// (https://github.com/dtolnay/cxx/issues/297#issuecomment-727042059)
37+
unsafe extern "C++" {
38+
include!("shell_wrapper/status.rs.h");
39+
type FfiStatus = status::ffi::FfiStatus;
40+
}
41+
42+
#[namespace = "secure_aggregation"]
43+
extern "Rust" {
44+
unsafe fn create_human_readable_shell_config(
45+
aggregation_config_proto: UniquePtr<CxxString>,
46+
out: *mut Vec<u8>,
47+
) -> FfiStatus;
48+
}
49+
}
50+
51+
fn create_human_readable_shell_config_impl(
52+
aggregation_config_proto: UniquePtr<CxxString>,
53+
) -> Result<Vec<u8>, status::StatusError> {
54+
let config_proto =
55+
AggregationConfigProto::parse(aggregation_config_proto.as_bytes()).map_err(|e| {
56+
status::invalid_argument(format!("Failed to parse AggregationConfigProto: {}", e))
57+
})?;
58+
let config = AggregationConfig::from_proto(config_proto, ())?;
59+
let (kahe_config, ahe_config) = create_shell_configs(&config)?;
60+
let kahe_config_string = format!("{:#?}", kahe_config);
61+
let ahe_config_string = format!("{:#?}", ahe_config);
62+
let result =
63+
format!("ShellKaheConfig: {}\nShellAheConfig: {}", kahe_config_string, ahe_config_string);
64+
Ok(result.into_bytes())
65+
}
66+
67+
/// SAFETY: `out` must not be null.
68+
unsafe fn create_human_readable_shell_config(
69+
aggregation_config_proto: UniquePtr<CxxString>,
70+
out: *mut Vec<u8>,
71+
) -> ffi::FfiStatus {
72+
create_human_readable_shell_config_impl(aggregation_config_proto)
73+
.map(|result| *out = result)
74+
.into()
75+
}
2676

2777
/// Convert a rust struct `PackedVectorConfig` to the corresponding proto.
2878
pub fn packed_vector_config_to_proto(config: &PackedVectorConfig) -> PackedVectorConfigProto {
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Copyright 2026 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "willow/src/shell/parameters_utils.h"
18+
19+
#include "absl/status/status.h"
20+
#include "gmock/gmock.h"
21+
#include "gtest/gtest.h"
22+
#include "willow/proto/willow/aggregation_config.pb.h"
23+
24+
namespace secure_aggregation {
25+
namespace willow {
26+
namespace {
27+
28+
TEST(ParameterUtilsTest, CreateHumanReadableShellConfigTest) {
29+
AggregationConfigProto config;
30+
VectorConfig vector_config;
31+
vector_config.set_length(10);
32+
vector_config.set_bound(100);
33+
(*config.mutable_vector_configs())["test_vector"] = vector_config;
34+
config.set_max_number_of_decryptors(1);
35+
config.set_max_number_of_clients(10);
36+
config.set_session_id("test_session");
37+
38+
auto result = CreateHumanReadableShellConfig(config);
39+
40+
ASSERT_TRUE(result.ok());
41+
EXPECT_THAT(*result, ::testing::HasSubstr("ShellKaheConfig"));
42+
EXPECT_THAT(*result, ::testing::HasSubstr("ShellAheConfig"));
43+
}
44+
45+
TEST(ParameterUtilsTest, CreateHumanReadableShellConfigInvalidConfigTest) {
46+
AggregationConfigProto config;
47+
config.set_max_number_of_decryptors(1);
48+
config.set_max_number_of_clients(10);
49+
config.set_session_id("test_session");
50+
51+
auto result = CreateHumanReadableShellConfig(config);
52+
53+
EXPECT_EQ(result.status().code(), absl::StatusCode::kInvalidArgument);
54+
EXPECT_THAT(
55+
result.status().message(),
56+
::testing::HasSubstr("empty vector configs in aggregation config"));
57+
}
58+
59+
} // namespace
60+
} // namespace willow
61+
} // namespace secure_aggregation

0 commit comments

Comments
 (0)