Skip to content

Commit d2b623b

Browse files
committed
Make it possible to cancel a simulation
1 parent bbc0019 commit d2b623b

3 files changed

Lines changed: 120 additions & 11 deletions

File tree

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/* SCL --- Secure Computation Library
2+
* Copyright (C) 2025 Anders Dalskov
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU Affero General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU Affero General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU Affero General Public License
15+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
16+
*/
17+
18+
#include <stdexcept>
19+
namespace scl {
20+
namespace details {
21+
22+
struct CancellationException final : public std::runtime_error {
23+
CancellationException() : std::runtime_error("cancelled") {}
24+
};
25+
26+
} // namespace details
27+
28+
inline void forceStopProtocol() {
29+
throw details::CancellationException{};
30+
}
31+
32+
} // namespace scl

src/scl/simulation/simulator.cc

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
#include "scl/net/loopback.h"
2424
#include "scl/protocol.h"
25+
#include "scl/simulation/cancellation.h"
2526
#include "scl/simulation/channel.h"
2627
#include "scl/simulation/context.h"
2728
#include "scl/simulation/event.h"
@@ -111,29 +112,25 @@ Task<void> runProtocol(std::unique_ptr<Protocol> protocol,
111112
ctx.addEvent<EndEvent>(et, protocol->name());
112113

113114
if (next.output.has_value()) {
115+
ctx.addEvent<OutputEvent>(et);
114116
ctx.output(next.output);
115117
}
116118

117-
// This will suspend this party, allowing someone else to run. It's not
118-
// really needed, but (hopefully) it ensures a more "fair" execution
119-
// order.
120-
//
121-
// TODO: Is this needed?
122-
co_await []() { return true; };
123-
124119
protocol = std::move(next.next);
125120
}
126121

127122
ctx.addEvent<StopEvent>(ctx.lastEvent()->time());
128123

129-
} catch (CancelledEvent&) {
124+
} catch (details::CancellationException& /* ignored */) {
130125
// this party was stopped by a user supplied hook.
131126
ctx.addEvent<CancelledEvent>(ctx.lastEvent()->time());
127+
co_return;
132128

133129
} catch (std::exception& e) {
134130
// all exceptions are caught and discarded, but we make sure to record an
135131
// event.
136132
ctx.addEvent<KilledEvent>(ctx.lastEvent()->time(), e.what());
133+
co_return;
137134
}
138135
}
139136

test/scl/simulation/test_simulator.cc

Lines changed: 83 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,12 @@
1717

1818
#include <any>
1919
#include <catch2/catch_test_macros.hpp>
20-
#include <initializer_list>
20+
#include <iostream>
2121
#include <memory>
2222

2323
#include "scl/coro.h"
2424
#include "scl/protocol.h"
25+
#include "scl/simulation/cancellation.h"
2526
#include "scl/simulation/event.h"
2627
#include "scl/simulation/params.h"
2728
#include "scl/simulation/simulator.h"
@@ -103,7 +104,7 @@ TEST_CASE("Simulator test", "[sim]") {
103104

104105
namespace {
105106

106-
struct OutputProtocol final : public Protocol {
107+
struct SimpleProtocol final : public Protocol {
107108
Task<Result> run(Env& /* ignored */) const override {
108109
co_return Result::done(123);
109110
}
@@ -125,10 +126,89 @@ TEST_CASE("Simulator handle output", "[sim]") {
125126
auto res = sim.run(
126127
[]() {
127128
std::vector<std::unique_ptr<Protocol>> p;
128-
p.emplace_back(std::make_unique<OutputProtocol>());
129+
p.emplace_back(std::make_unique<SimpleProtocol>());
129130
return p;
130131
},
131132
nd);
132133

133134
REQUIRE(called);
134135
}
136+
137+
TEST_CASE("Simulator hooks no trigger", "[sim]") {
138+
auto nd = NetworkParams::create(1);
139+
140+
std::size_t num_called = 0;
141+
142+
Simulator sim;
143+
sim.addHook([&num_called](std::size_t /* ignored*/, Event* /* ignored*/) {
144+
num_called++;
145+
});
146+
147+
auto res = sim.run(
148+
[]() {
149+
std::vector<std::unique_ptr<Protocol>> p;
150+
p.emplace_back(std::make_unique<SimpleProtocol>());
151+
return p;
152+
},
153+
nd);
154+
155+
REQUIRE(num_called == res[0].size());
156+
}
157+
158+
TEST_CASE("Simulator hooks with trigger", "[sim]") {
159+
auto nd = NetworkParams::create(1);
160+
161+
bool start_hook_called = false;
162+
bool send_hook_called = false;
163+
164+
Simulator sim;
165+
166+
// should be called
167+
sim.addHook(EventType::START,
168+
[&start_hook_called](std::size_t pid, Event* evt) {
169+
start_hook_called =
170+
(pid == 0) && (evt->type() == EventType::START);
171+
});
172+
173+
// should not be called
174+
sim.addHook(
175+
EventType::CHANNEL_SEND,
176+
[&send_hook_called](std::size_t /* ignored*/, Event* /* ignored*/) {
177+
send_hook_called = true;
178+
});
179+
180+
auto res = sim.run(
181+
[]() {
182+
std::vector<std::unique_ptr<Protocol>> p;
183+
p.emplace_back(std::make_unique<SimpleProtocol>());
184+
return p;
185+
},
186+
nd);
187+
188+
REQUIRE(start_hook_called);
189+
REQUIRE_FALSE(send_hook_called);
190+
}
191+
192+
TEST_CASE("Simulator cancellation", "[sim]") {
193+
auto nd = NetworkParams::create(2);
194+
195+
Simulator sim;
196+
197+
sim.addHook(EventType::START,
198+
[](std::size_t /* ignored */, Event* /* ignored */) {
199+
forceStopProtocol();
200+
});
201+
202+
auto res = sim.run(
203+
[]() {
204+
std::vector<std::unique_ptr<Protocol>> p;
205+
p.emplace_back(std::make_unique<SimpleProtocol>());
206+
p.emplace_back(std::make_unique<SimpleProtocol>());
207+
return p;
208+
},
209+
nd);
210+
211+
REQUIRE(res.numberOfParties() == 2);
212+
213+
assertEvents(res[0], {EventType::START, EventType::CANCELLED});
214+
}

0 commit comments

Comments
 (0)