Skip to content

Commit cde7071

Browse files
authored
refactor: Consolidate how system state modifications are extracted from the System API (#3706)
Currently, there are two similar functions in the `SystemApiImpl` to extract system state modifications. One of them `take_system_state_modifications` is used in the sandbox when preparing the state changes to be transmitted back to the replica. Then, the replica after deserializing the result that it receives from the sandbox calls `into_system_state_changes` on the reconstructed `system_api` to extract the changes again. In a recent [PR](#363), `into_system_state_modifications` was changed (to make it more clear which changes are relevant per message type) but `take_system_state_modifications` wasn't. This works correctly because `into_system_state_modifications` is the last one that's called before applying the state changes back to the canister state. However, it's also a very clear example of how the code can easily diverge and go unnoticed, potentially with more severe implications in the future. This PR proposes to use one function which seems to provide the usual benefits of consistent way of applying the changes and "having one way" of doing the same task. We keep `take_system_state_modifications` (this allows us to get rid of some `clone`s but more importantly it's needed in the sandbox, see comment in the existing code) and change the call sites respectively.
1 parent eb4a6d5 commit cde7071

File tree

5 files changed

+20
-50
lines changed

5 files changed

+20
-50
lines changed

rs/canister_sandbox/src/sandbox_manager.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ impl Execution {
173173
.system_api_mut()
174174
.expect("System api not present in the wasmtime instance")
175175
.take_system_state_modifications(),
176-
Err(system_api) => system_api.into_system_state_modifications(),
176+
Err(mut system_api) => system_api.take_system_state_modifications(),
177177
};
178178

179179
let execution_state_modifications = deltas.map(

rs/embedders/src/wasm_executor.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -258,11 +258,11 @@ impl WasmExecutor for WasmExecutorImpl {
258258
}),
259259
None => None,
260260
};
261-
let system_api = match instance_or_system_api {
261+
let mut system_api = match instance_or_system_api {
262262
Ok(instance) => instance.into_store_data().system_api.unwrap(),
263263
Err(system_api) => system_api,
264264
};
265-
let system_state_modifications = system_api.into_system_state_modifications();
265+
let system_state_modifications = system_api.take_system_state_modifications();
266266

267267
(
268268
compilation_result,

rs/system_api/src/lib.rs

Lines changed: 10 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1494,7 +1494,8 @@ impl SystemApiImpl {
14941494
}
14951495
}
14961496

1497-
pub fn into_system_state_modifications(self) -> SystemStateModifications {
1497+
pub fn take_system_state_modifications(&mut self) -> SystemStateModifications {
1498+
let system_state_modifications = self.sandbox_safe_system_state.take_changes();
14981499
match self.api_type {
14991500
// List all fields of `SystemStateModifications` so that
15001501
// there's an explicit decision that needs to be made
@@ -1514,53 +1515,28 @@ impl SystemApiImpl {
15141515
},
15151516
ApiType::NonReplicatedQuery { .. } => SystemStateModifications {
15161517
new_certified_data: None,
1517-
callback_updates: self
1518-
.sandbox_safe_system_state
1519-
.system_state_modifications
1520-
.callback_updates
1521-
.clone(),
1518+
callback_updates: system_state_modifications.callback_updates,
15221519
cycles_balance_change: CyclesBalanceChange::zero(),
15231520
reserved_cycles: Cycles::zero(),
15241521
consumed_cycles_by_use_case: BTreeMap::new(),
15251522
call_context_balance_taken: None,
1526-
request_slots_used: self
1527-
.sandbox_safe_system_state
1528-
.system_state_modifications
1529-
.request_slots_used
1530-
.clone(),
1531-
requests: self
1532-
.sandbox_safe_system_state
1533-
.system_state_modifications
1534-
.requests
1535-
.clone(),
1523+
request_slots_used: system_state_modifications.request_slots_used,
1524+
requests: system_state_modifications.requests,
15361525
new_global_timer: None,
15371526
canister_log: Default::default(),
15381527
on_low_wasm_memory_hook_condition_check_result: None,
15391528
},
15401529
ApiType::ReplicatedQuery { .. } => SystemStateModifications {
15411530
new_certified_data: None,
15421531
callback_updates: vec![],
1543-
cycles_balance_change: self
1544-
.sandbox_safe_system_state
1545-
.system_state_modifications
1546-
.cycles_balance_change,
1532+
cycles_balance_change: system_state_modifications.cycles_balance_change,
15471533
reserved_cycles: Cycles::zero(),
1548-
consumed_cycles_by_use_case: self
1549-
.sandbox_safe_system_state
1550-
.system_state_modifications
1551-
.consumed_cycles_by_use_case,
1552-
call_context_balance_taken: self
1553-
.sandbox_safe_system_state
1554-
.system_state_modifications
1555-
.call_context_balance_taken,
1534+
consumed_cycles_by_use_case: system_state_modifications.consumed_cycles_by_use_case,
1535+
call_context_balance_taken: system_state_modifications.call_context_balance_taken,
15561536
request_slots_used: BTreeMap::new(),
15571537
requests: vec![],
15581538
new_global_timer: None,
1559-
canister_log: self
1560-
.sandbox_safe_system_state
1561-
.system_state_modifications
1562-
.canister_log
1563-
.clone(),
1539+
canister_log: system_state_modifications.canister_log,
15641540
on_low_wasm_memory_hook_condition_check_result: None,
15651541
},
15661542
ApiType::Start { .. }
@@ -1570,16 +1546,10 @@ impl SystemApiImpl {
15701546
| ApiType::Update { .. }
15711547
| ApiType::Cleanup { .. }
15721548
| ApiType::ReplyCallback { .. }
1573-
| ApiType::RejectCallback { .. } => {
1574-
self.sandbox_safe_system_state.system_state_modifications
1575-
}
1549+
| ApiType::RejectCallback { .. } => system_state_modifications,
15761550
}
15771551
}
15781552

1579-
pub fn take_system_state_modifications(&mut self) -> SystemStateModifications {
1580-
self.sandbox_safe_system_state.take_changes()
1581-
}
1582-
15831553
pub fn stable_memory_size(&self) -> NumWasmPages {
15841554
self.stable_memory().stable_memory_size
15851555
}

rs/system_api/tests/sandbox_safe_system_state.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,7 @@ fn call_increases_cycles_consumed_metric() {
443443
api.ic0_call_new(0, 0, 0, 0, 0, 0, 0, 0, &[]).unwrap();
444444
api.ic0_call_perform().unwrap();
445445

446-
let system_state_modifications = api.into_system_state_modifications();
446+
let system_state_modifications = api.take_system_state_modifications();
447447
system_state_modifications
448448
.apply_changes(
449449
UNIX_EPOCH,

rs/system_api/tests/system_api.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1164,7 +1164,7 @@ fn certified_data_set() {
11641164
// Copy the certified data into the system state.
11651165
api.ic0_certified_data_set(0, 32, &heap).unwrap();
11661166

1167-
let system_state_modifications = api.into_system_state_modifications();
1167+
let system_state_modifications = api.take_system_state_modifications();
11681168
system_state_modifications
11691169
.apply_changes(
11701170
UNIX_EPOCH,
@@ -1337,7 +1337,7 @@ fn call_perform_not_enough_cycles_does_not_trap() {
13371337
res
13381338
),
13391339
}
1340-
let system_state_modifications = api.into_system_state_modifications();
1340+
let system_state_modifications = api.take_system_state_modifications();
13411341
system_state_modifications
13421342
.apply_changes(
13431343
UNIX_EPOCH,
@@ -1481,7 +1481,7 @@ fn helper_test_on_low_wasm_memory(
14811481
.unwrap();
14821482
}
14831483

1484-
let system_state_modifications = api.into_system_state_modifications();
1484+
let system_state_modifications = api.take_system_state_modifications();
14851485
system_state_modifications
14861486
.apply_changes(
14871487
UNIX_EPOCH,
@@ -1750,7 +1750,7 @@ fn push_output_request_respects_memory_limits() {
17501750
);
17511751

17521752
// Ensure that exactly one output request was pushed.
1753-
let system_state_modifications = api.into_system_state_modifications();
1753+
let system_state_modifications = api.take_system_state_modifications();
17541754
system_state_modifications
17551755
.apply_changes(
17561756
UNIX_EPOCH,
@@ -1866,7 +1866,7 @@ fn push_output_request_oversized_request_memory_limits() {
18661866
);
18671867

18681868
// Ensure that exactly one output request was pushed.
1869-
let system_state_modifications = api.into_system_state_modifications();
1869+
let system_state_modifications = api.take_system_state_modifications();
18701870
system_state_modifications
18711871
.apply_changes(
18721872
UNIX_EPOCH,
@@ -1902,7 +1902,7 @@ fn ic0_global_timer_set_is_propagated_from_sandbox() {
19021902

19031903
// Propagate system state changes
19041904
assert_eq!(system_state.global_timer, CanisterTimer::Inactive);
1905-
let system_state_modifications = api.into_system_state_modifications();
1905+
let system_state_modifications = api.take_system_state_modifications();
19061906
system_state_modifications
19071907
.apply_changes(
19081908
UNIX_EPOCH,

0 commit comments

Comments
 (0)