Skip to content

Commit d1a81e6

Browse files
authored
refactor(flexible-outcalls): remove obsolete subnet_size param from context's generate_from_args (#9037)
Removes the obsolete `subnet_size` param from `CanisterHttpRequestContext::generate_from_args` and use `node_ids.len()` instead, while rejecting empty node_ids with `NoNodesAvailableForDelegation`, so as to make the API less confusing. This is done because in production, `subnet_size` and `node_ids.len()` are the same, except for the special (critical error) case when the subnet record's `membership` is empty: * `node_ids` is derived from the registry's subnet record's membership [here](https://github.com/dfinity/ic/blob/4bb874fc5cc90e25ef1b003f932a48da40eb34a6/rs/messaging/src/message_routing.rs#L862-L869) (de-duplicated via `BTreeSet`) * `subnet_size` is also calculated from the registry's subnet record's membership [here](https://github.com/dfinity/ic/blob/master/rs/messaging/src/message_routing.rs#L905-L919) (de-duplicated via `BTreeSet`), **BUT** there is a fallback when the membership is empty, namely to `SMALL_APP_SUBNET_MAX_SIZE` (13) with a warn! log (while the `node_ids` remain empty). * Also in some tests, the two [can diverge](https://github.com/dfinity/ic/blob/4bb874fc5cc90e25ef1b003f932a48da40eb34a6/rs/test_utilities/execution_environment/src/lib.rs#L206-L215), which is irrelevant here.
1 parent 2e61b35 commit d1a81e6

4 files changed

Lines changed: 33 additions & 14 deletions

File tree

rs/execution_environment/src/execution_environment.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1104,7 +1104,6 @@ impl ExecutionEnvironment {
11041104
request.as_ref(),
11051105
args,
11061106
&registry_settings.node_ids,
1107-
registry_settings.subnet_size,
11081107
rng,
11091108
) {
11101109
Err(err) => ExecuteSubnetMessageResult::Finished {

rs/test_utilities/execution_environment/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,9 @@ pub fn test_registry_settings() -> RegistryExecutionSettings {
216216
provisional_whitelist: ProvisionalWhitelist::Set(BTreeSet::new()),
217217
chain_key_settings: BTreeMap::new(),
218218
subnet_size: SMALL_APP_SUBNET_MAX_SIZE,
219-
node_ids: BTreeSet::new(),
219+
node_ids: (0..SMALL_APP_SUBNET_MAX_SIZE)
220+
.map(|i| node_test_id(i as u64))
221+
.collect(),
220222
registry_version: RegistryVersion::default(),
221223
}
222224
}

rs/tests/networking/canister_http_correctness_test.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use ic_agent::{
2525
Agent, AgentError,
2626
agent::{RejectCode, RejectResponse},
2727
};
28-
use ic_base_types::{CanisterId, NumBytes};
28+
use ic_base_types::{CanisterId, NumBytes, PrincipalId};
2929
use ic_cdk::api::call::RejectionCode;
3030
use ic_management_canister_types_private::{
3131
HttpHeader, HttpMethod, TransformContext, TransformFunc,
@@ -2642,8 +2642,7 @@ fn expected_cycle_cost(
26422642
.sender(proxy_canister)
26432643
.build(),
26442644
request.into(),
2645-
&BTreeSet::new(),
2646-
0,
2645+
&BTreeSet::from([PrincipalId::new_node_test_id(0).into()]),
26472646
&mut rand::thread_rng(),
26482647
)
26492648
.unwrap();

rs/types/types/src/canister_http.rs

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -507,12 +507,14 @@ impl CanisterHttpRequestContext {
507507
request: &Request,
508508
args: CanisterHttpRequestArgs,
509509
node_ids: &BTreeSet<NodeId>,
510-
subnet_size: usize,
511510
rng: &mut dyn RngCore,
512511
) -> Result<Self, CanisterHttpRequestContextError> {
513512
validate_transform_principal(&args.transform, request.sender.get())?;
514513
validate_url_length(&args.url)?;
515514
validate_http_headers_and_body(args.headers.get(), args.body.as_ref().unwrap_or(&vec![]))?;
515+
if node_ids.is_empty() {
516+
return Err(CanisterHttpRequestContextError::NoNodesAvailableForDelegation);
517+
}
516518

517519
let max_response_bytes = match args.max_response_bytes {
518520
Some(max_response_bytes) => {
@@ -579,7 +581,7 @@ impl CanisterHttpRequestContext {
579581
refund_status: RefundStatus {
580582
//TODO(IC-1937): subtract the base fee from the refundable amount.
581583
refundable_cycles: request.payment,
582-
per_replica_allowance: request.payment / subnet_size.max(1),
584+
per_replica_allowance: request.payment / node_ids.len(),
583585
refunded_cycles: Cycles::new(0),
584586
refunding_nodes: BTreeSet::new(),
585587
},
@@ -1247,7 +1249,7 @@ mod tests {
12471249
// PUT with is_replicated None -> rejected
12481250
let args = dummy_args(HttpMethod::PUT, None);
12491251
let result = CanisterHttpRequestContext::generate_from_args(
1250-
UNIX_EPOCH, &request, args, &node_ids, 1, rng,
1252+
UNIX_EPOCH, &request, args, &node_ids, rng,
12511253
);
12521254
assert_matches!(
12531255
result,
@@ -1257,7 +1259,7 @@ mod tests {
12571259
// PUT with is_replicated Some(true) -> rejected
12581260
let args = dummy_args(HttpMethod::PUT, Some(true));
12591261
let result = CanisterHttpRequestContext::generate_from_args(
1260-
UNIX_EPOCH, &request, args, &node_ids, 1, rng,
1262+
UNIX_EPOCH, &request, args, &node_ids, rng,
12611263
);
12621264
assert_matches!(
12631265
result,
@@ -1267,7 +1269,7 @@ mod tests {
12671269
// PUT with is_replicated Some(false) -> accepted
12681270
let args = dummy_args(HttpMethod::PUT, Some(false));
12691271
let result = CanisterHttpRequestContext::generate_from_args(
1270-
UNIX_EPOCH, &request, args, &node_ids, 1, rng,
1272+
UNIX_EPOCH, &request, args, &node_ids, rng,
12711273
);
12721274
assert_matches!(
12731275
result,
@@ -1287,7 +1289,7 @@ mod tests {
12871289
// DELETE with is_replicated None -> rejected
12881290
let args = dummy_args(HttpMethod::DELETE, None);
12891291
let result = CanisterHttpRequestContext::generate_from_args(
1290-
UNIX_EPOCH, &request, args, &node_ids, 1, rng,
1292+
UNIX_EPOCH, &request, args, &node_ids, rng,
12911293
);
12921294
assert_matches!(
12931295
result,
@@ -1297,7 +1299,7 @@ mod tests {
12971299
// DELETE with is_replicated Some(true) -> rejected
12981300
let args = dummy_args(HttpMethod::DELETE, Some(true));
12991301
let result = CanisterHttpRequestContext::generate_from_args(
1300-
UNIX_EPOCH, &request, args, &node_ids, 1, rng,
1302+
UNIX_EPOCH, &request, args, &node_ids, rng,
13011303
);
13021304
assert_matches!(
13031305
result,
@@ -1307,7 +1309,7 @@ mod tests {
13071309
// DELETE with is_replicated Some(false) -> accepted
13081310
let args = dummy_args(HttpMethod::DELETE, Some(false));
13091311
let result = CanisterHttpRequestContext::generate_from_args(
1310-
UNIX_EPOCH, &request, args, &node_ids, 1, rng,
1312+
UNIX_EPOCH, &request, args, &node_ids, rng,
13111313
);
13121314
assert_matches!(
13131315
result,
@@ -1335,7 +1337,7 @@ mod tests {
13351337
});
13361338

13371339
let result = CanisterHttpRequestContext::generate_from_args(
1338-
UNIX_EPOCH, &request, args, &node_ids, 1, rng,
1340+
UNIX_EPOCH, &request, args, &node_ids, rng,
13391341
);
13401342

13411343
assert_matches!(
@@ -1344,6 +1346,23 @@ mod tests {
13441346
);
13451347
}
13461348

1349+
#[test]
1350+
fn rejects_empty_node_ids() {
1351+
let rng = &mut ReproducibleRng::new();
1352+
let node_ids = BTreeSet::new();
1353+
let request = dummy_request();
1354+
let args = dummy_args(HttpMethod::GET, None);
1355+
1356+
let result = CanisterHttpRequestContext::generate_from_args(
1357+
UNIX_EPOCH, &request, args, &node_ids, rng,
1358+
);
1359+
1360+
assert_matches!(
1361+
result,
1362+
Err(CanisterHttpRequestContextError::NoNodesAvailableForDelegation)
1363+
);
1364+
}
1365+
13471366
#[test]
13481367
fn flexible_rejects_invalid_transform_principal() {
13491368
let rng = &mut ReproducibleRng::new();

0 commit comments

Comments
 (0)