Skip to content
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions rs/embedders/src/wasmtime_embedder/system_api/routing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ pub(super) fn resolve_destination(
| Ok(Ic00Method::RawRand)
| Ok(Ic00Method::ProvisionalCreateCanisterWithCycles)
| Ok(Ic00Method::HttpRequest)
| Ok(Ic00Method::FlexibleHttpRequest)
| Ok(Ic00Method::BitcoinSendTransactionInternal)
| Ok(Ic00Method::BitcoinGetSuccessors) => Ok(own_subnet.get()),
// This message needs to be routed to the NNS subnet. We assume that
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ impl SystemStateModifications {
| Ok(Ic00Method::DeleteCanister)
| Ok(Ic00Method::RawRand)
| Ok(Ic00Method::DepositCycles)
| Ok(Ic00Method::FlexibleHttpRequest)
| Ok(Ic00Method::HttpRequest)
| Ok(Ic00Method::SetupInitialDKG)
| Ok(Ic00Method::ECDSAPublicKey)
Expand Down
1 change: 1 addition & 0 deletions rs/execution_environment/src/canister_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ impl CanisterManager {
// cannot carry cycles, it does not make sense to allow them from users.
| Ok(Ic00Method::DepositCycles)
| Ok(Ic00Method::HttpRequest)
| Ok(Ic00Method::FlexibleHttpRequest)
// Nobody pays for `raw_rand`, so this cannot be used via ingress messages
| Ok(Ic00Method::RawRand)
// Bitcoin messages require cycles, so we reject all ingress messages.
Expand Down
57 changes: 46 additions & 11 deletions rs/execution_environment/src/execution_environment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,17 @@ use ic_management_canister_types_private::{
CanisterChangeOrigin, CanisterHttpRequestArgs, CanisterIdRecord, CanisterInfoRequest,
CanisterInfoResponse, CanisterMetadataRequest, CanisterStatusType, ClearChunkStoreArgs,
CreateCanisterArgs, DeleteCanisterSnapshotArgs, ECDSAPublicKeyArgs, ECDSAPublicKeyResponse,
EmptyBlob, FetchCanisterLogsRequest, IC_00, InstallChunkedCodeArgs, InstallCodeArgsV2,
ListCanisterSnapshotArgs, LoadCanisterSnapshotArgs, MasterPublicKeyId, Method as Ic00Method,
NodeMetricsHistoryArgs, Payload as Ic00Payload, ProvisionalCreateCanisterWithCyclesArgs,
ProvisionalTopUpCanisterArgs, ReadCanisterSnapshotDataArgs, ReadCanisterSnapshotMetadataArgs,
RenameCanisterArgs, ReshareChainKeyArgs, SchnorrAlgorithm, SchnorrPublicKeyArgs,
SchnorrPublicKeyResponse, SetupInitialDKGArgs, SignWithECDSAArgs, SignWithSchnorrArgs,
SignWithSchnorrAux, StoredChunksArgs, SubnetInfoArgs, SubnetInfoResponse,
TakeCanisterSnapshotArgs, UninstallCodeArgs, UpdateSettingsArgs,
UploadCanisterSnapshotDataArgs, UploadCanisterSnapshotMetadataArgs,
UploadCanisterSnapshotMetadataResponse, UploadChunkArgs, VetKdDeriveKeyArgs,
VetKdPublicKeyArgs, VetKdPublicKeyResult,
EmptyBlob, FetchCanisterLogsRequest, FlexibleCanisterHttpRequestArgs, IC_00,
InstallChunkedCodeArgs, InstallCodeArgsV2, ListCanisterSnapshotArgs, LoadCanisterSnapshotArgs,
MasterPublicKeyId, Method as Ic00Method, NodeMetricsHistoryArgs, Payload as Ic00Payload,
ProvisionalCreateCanisterWithCyclesArgs, ProvisionalTopUpCanisterArgs,
ReadCanisterSnapshotDataArgs, ReadCanisterSnapshotMetadataArgs, RenameCanisterArgs,
ReshareChainKeyArgs, SchnorrAlgorithm, SchnorrPublicKeyArgs, SchnorrPublicKeyResponse,
SetupInitialDKGArgs, SignWithECDSAArgs, SignWithSchnorrArgs, SignWithSchnorrAux,
StoredChunksArgs, SubnetInfoArgs, SubnetInfoResponse, TakeCanisterSnapshotArgs,
UninstallCodeArgs, UpdateSettingsArgs, UploadCanisterSnapshotDataArgs,
UploadCanisterSnapshotMetadataArgs, UploadCanisterSnapshotMetadataResponse, UploadChunkArgs,
VetKdDeriveKeyArgs, VetKdPublicKeyArgs, VetKdPublicKeyResult,
};
use ic_metrics::MetricsRegistry;
use ic_registry_provisional_whitelist::ProvisionalWhitelist;
Expand Down Expand Up @@ -1000,6 +1000,41 @@ impl ExecutionEnvironment {
Ok(args) => self.deposit_cycles(args.get_canister_id(), &mut msg, &mut state),
},

Ok(Ic00Method::FlexibleHttpRequest) => {
match state.metadata.own_subnet_features.http_requests {
true => match &msg {
CanisterCall::Request(_) => {
match FlexibleCanisterHttpRequestArgs::decode(payload) {
Err(err) => ExecuteSubnetMessageResult::Finished {
response: Err(err),
refund: msg.take_cycles(),
},
Ok(_) => ExecuteSubnetMessageResult::Finished {
response: Err(UserError::new(
ErrorCode::CanisterRejectedMessage,
"FlexibleHttpRequest is not yet implemented".to_string(),
)),
refund: msg.take_cycles(),
},
}
}
CanisterCall::Ingress(_) => {
self.reject_unexpected_ingress(Ic00Method::FlexibleHttpRequest)
}
},
false => {
let err = Err(UserError::new(
ErrorCode::CanisterContractViolation,
"This API is not enabled on this subnet".to_string(),
));
ExecuteSubnetMessageResult::Finished {
response: err,
refund: msg.take_cycles(),
}
}
}
}

Ok(Ic00Method::HttpRequest) => match state.metadata.own_subnet_features.http_requests {
true => match &msg {
CanisterCall::Request(request) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,7 @@ impl ExecutionEnvironmentMetrics {
| ic00::Method::InstallChunkedCode
| ic00::Method::StopCanister
| ic00::Method::HttpRequest
| ic00::Method::FlexibleHttpRequest
| ic00::Method::SignWithECDSA
| ic00::Method::SignWithSchnorr
| ic00::Method::VetKdDeriveKey
Expand Down
5 changes: 4 additions & 1 deletion rs/execution_environment/src/ic00_permissions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,10 @@ impl Ic00MethodPermissions {
does_not_run_on_aborted_canister: false,
installs_code: false,
},
Ic00Method::CreateCanister | Ic00Method::HttpRequest | Ic00Method::RawRand => Self {
Ic00Method::CreateCanister
| Ic00Method::HttpRequest
| Ic00Method::FlexibleHttpRequest
| Ic00Method::RawRand => Self {
method,
allow_remote_subnet_sender: false,
allow_only_nns_subnet_sender: false,
Expand Down
1 change: 1 addition & 0 deletions rs/execution_environment/src/scheduler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2274,6 +2274,7 @@ fn get_instructions_limits_for_subnet_message(
| ECDSAPublicKey
| RawRand
| HttpRequest
| FlexibleHttpRequest
| SetupInitialDKG
| SignWithECDSA
| ReshareChainKey
Expand Down
1 change: 1 addition & 0 deletions rs/execution_environment/tests/dts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1135,6 +1135,7 @@ fn dts_aborted_execution_does_not_block_subnet_messages() {
// No effective canister id.
Method::CreateCanister
| Method::HttpRequest
| Method::FlexibleHttpRequest
| Method::ECDSAPublicKey
| Method::RawRand
| Method::SetupInitialDKG
Expand Down
9 changes: 8 additions & 1 deletion rs/rust_canisters/proxy_canister/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ use std::time::Duration;
use candid::{CandidType, Deserialize};
use ic_cdk::api::call::RejectionCode;
use ic_management_canister_types_private::{
BoundedHttpHeaders, HttpHeader, HttpMethod, Payload, TransformContext,
BoundedHttpHeaders, FlexibleCanisterHttpRequestArgs, HttpHeader, HttpMethod, Payload,
TransformContext,
};

#[derive(Clone, Debug, CandidType, Deserialize)]
Expand All @@ -27,6 +28,12 @@ pub struct RemoteHttpStressRequest {
pub count: u64,
}

#[derive(Clone, Debug, CandidType, Deserialize)]
pub struct FlexibleRemoteHttpRequest {
pub request: FlexibleCanisterHttpRequestArgs,
pub cycles: u64,
}

/// We create a custom type instead of reusing [`ic_management_canister_types_private::CanisterHttpRequestArgs`]
/// as we don't want the body to be deserialized as a bounded vec.
/// This allows us to test sending headers that are longer than the default limit and test.
Expand Down
20 changes: 18 additions & 2 deletions rs/rust_canisters/proxy_canister/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ use ic_management_canister_types_private::{
CanisterHttpResponsePayload, HttpHeader, Payload, TransformArgs,
};
use proxy_canister::{
RemoteHttpRequest, RemoteHttpResponse, RemoteHttpStressRequest, RemoteHttpStressResponse,
ResponseWithRefundedCycles,
FlexibleRemoteHttpRequest, RemoteHttpRequest, RemoteHttpResponse, RemoteHttpStressRequest,
RemoteHttpStressResponse, ResponseWithRefundedCycles,
};
use std::cell::RefCell;
use std::collections::HashMap;
Expand All @@ -31,6 +31,21 @@ thread_local! {

const MAX_TRANSFORM_SIZE: usize = 2_000_000;

#[update]
async fn send_flexible_request(
request: FlexibleRemoteHttpRequest,
) -> Result<Vec<u8>, (RejectionCode, String)> {
let FlexibleRemoteHttpRequest { request, cycles } = request;

ic_cdk::api::call::call_raw(
Principal::management_canister(),
"flexible_http_request",
&request.encode(),
cycles,
)
.await
}

#[update]
async fn send_requests_in_parallel(
request: RemoteHttpStressRequest,
Expand Down Expand Up @@ -116,6 +131,7 @@ async fn send_request_with_refund_callback(
let RemoteHttpRequest { request, cycles } = request;
let request_url = request.url.clone();
println!("send_request making IC call.");

let result = match ic_cdk::api::call::call_raw(
Principal::management_canister(),
"http_request",
Expand Down
81 changes: 37 additions & 44 deletions rs/tests/networking/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
load("@rules_rust//rust:defs.bzl", "rust_binary")
load("//rs/tests:common.bzl", "CANISTER_HTTP_DATA", "COUNTER_CANISTER_RUNTIME_DEPS", "MESSAGE_CANISTER_RUNTIME_DEPS", "UNIVERSAL_CANISTER_RUNTIME_DEPS")
load("//rs/tests:common.bzl", "COUNTER_CANISTER_RUNTIME_DEPS", "MESSAGE_CANISTER_RUNTIME_DEPS", "UNIVERSAL_CANISTER_RUNTIME_DEPS")
load("//rs/tests:system_tests.bzl", "system_test", "system_test_nns")

package(default_visibility = ["//rs:system-tests-pkg"])

PROXY_CANISTER_DATA = [
# Keep sorted.
"//rs/rust_canisters/proxy_canister:proxy_canister",
]
CANISTER_HTTP_RUNTIME_DEPS = {
"HTTP_UVM_CONFIG_IMAGE_PATH": "//rs/tests/networking/canister_http:http_uvm_config_image",
}

CANISTER_HTTP_BASE_DEPS = [
# Keep sorted.
Expand Down Expand Up @@ -53,27 +52,33 @@ HTTP_ENDPOINTS_DEPS = [

system_test_nns(
name = "canister_http_test",
data =
CANISTER_HTTP_DATA + PROXY_CANISTER_DATA,
env = {
"PROXY_WASM_PATH": "$(rootpath //rs/rust_canisters/proxy_canister:proxy_canister)",
},
tags = [
"long_test", # since it takes longer than 5 minutes.
],
runtime_deps = CANISTER_HTTP_RUNTIME_DEPS | {
"PROXY_WASM_PATH": "//rs/rust_canisters/proxy_canister:proxy_canister",
},
deps = CANISTER_HTTP_BASE_DEPS + ["//rs/rust_canisters/canister_test"],
)

system_test_nns(
name = "canister_http_flexible_test",
runtime_deps = CANISTER_HTTP_RUNTIME_DEPS | {
"PROXY_WASM_PATH": "//rs/rust_canisters/proxy_canister:proxy_canister",
},
deps = CANISTER_HTTP_BASE_DEPS + [
"//rs/rust_canisters/canister_test",
],
)

system_test_nns(
name = "canister_http_stress_test",
data =
CANISTER_HTTP_DATA + PROXY_CANISTER_DATA,
enable_metrics = True,
env = {
"PROXY_WASM_PATH": "$(rootpath //rs/rust_canisters/proxy_canister:proxy_canister)",
},
tags = ["manual"], # not meant to be run on CI
test_timeout = "eternal",
runtime_deps = CANISTER_HTTP_RUNTIME_DEPS | {
"PROXY_WASM_PATH": "//rs/rust_canisters/proxy_canister:proxy_canister",
},
deps = CANISTER_HTTP_BASE_DEPS + [
"//rs/registry/subnet_features",
"//rs/registry/subnet_type",
Expand All @@ -88,17 +93,15 @@ system_test_nns(

system_test_nns(
name = "canister_http_soak_test",
data =
CANISTER_HTTP_DATA + PROXY_CANISTER_DATA,
enable_metrics = True,
env = {
"PROXY_WASM_PATH": "$(rootpath //rs/rust_canisters/proxy_canister:proxy_canister)",
},
tags = [
"dynamic_testnet",
"manual",
],
test_timeout = "eternal",
runtime_deps = CANISTER_HTTP_RUNTIME_DEPS | {
"PROXY_WASM_PATH": "//rs/rust_canisters/proxy_canister:proxy_canister",
},
deps = CANISTER_HTTP_BASE_DEPS + [
"//rs/registry/subnet_features",
"//rs/registry/subnet_type",
Expand All @@ -114,15 +117,13 @@ system_test_nns(
# NOTE: This test is currently non-functional because API boundary nodes running GuestOS on Farm VMs do not support IPv4.
system_test_nns(
name = "canister_http_socks_test",
data =
CANISTER_HTTP_DATA + PROXY_CANISTER_DATA,
env = {
"PROXY_WASM_PATH": "$(rootpath //rs/rust_canisters/proxy_canister:proxy_canister)",
},
tags = [
"dynamic_testnet",
"long_test",
],
runtime_deps = CANISTER_HTTP_RUNTIME_DEPS | {
"PROXY_WASM_PATH": "//rs/rust_canisters/proxy_canister:proxy_canister",
},
deps = CANISTER_HTTP_BASE_DEPS + [
"//rs/registry/subnet_features",
"//rs/registry/subnet_type",
Expand All @@ -132,10 +133,8 @@ system_test_nns(

system_test_nns(
name = "canister_http_correctness_test",
data =
CANISTER_HTTP_DATA + PROXY_CANISTER_DATA,
env = {
"PROXY_WASM_PATH": "$(rootpath //rs/rust_canisters/proxy_canister:proxy_canister)",
runtime_deps = CANISTER_HTTP_RUNTIME_DEPS | {
"PROXY_WASM_PATH": "//rs/rust_canisters/proxy_canister:proxy_canister",
},
deps = CANISTER_HTTP_BASE_DEPS + [
"//rs/registry/subnet_type",
Expand All @@ -155,14 +154,12 @@ system_test_nns(

system_test_nns(
name = "canister_http_fault_tolerance_test",
data =
CANISTER_HTTP_DATA + PROXY_CANISTER_DATA,
env = {
"PROXY_WASM_PATH": "$(rootpath //rs/rust_canisters/proxy_canister:proxy_canister)",
},
tags = [
"manual",
],
runtime_deps = CANISTER_HTTP_RUNTIME_DEPS | {
"PROXY_WASM_PATH": "//rs/rust_canisters/proxy_canister:proxy_canister",
},
deps = CANISTER_HTTP_BASE_DEPS + [
"//rs/registry/subnet_type",
"//rs/rust_canisters/canister_test",
Expand All @@ -175,24 +172,20 @@ system_test_nns(

system_test_nns(
name = "canister_http_non_replicated_test",
data =
CANISTER_HTTP_DATA + PROXY_CANISTER_DATA,
env = {
"PROXY_WASM_PATH": "$(rootpath //rs/rust_canisters/proxy_canister:proxy_canister)",
runtime_deps = CANISTER_HTTP_RUNTIME_DEPS | {
"PROXY_WASM_PATH": "//rs/rust_canisters/proxy_canister:proxy_canister",
},
deps = CANISTER_HTTP_BASE_DEPS + ["//rs/rust_canisters/canister_test"],
)

system_test_nns(
name = "canister_http_time_out_test",
data =
CANISTER_HTTP_DATA + PROXY_CANISTER_DATA,
env = {
"PROXY_WASM_PATH": "$(rootpath //rs/rust_canisters/proxy_canister:proxy_canister)",
},
tags = [
"long_test",
],
runtime_deps = CANISTER_HTTP_RUNTIME_DEPS | {
"PROXY_WASM_PATH": "//rs/rust_canisters/proxy_canister:proxy_canister",
},
deps = CANISTER_HTTP_BASE_DEPS,
)

Expand Down Expand Up @@ -466,4 +459,4 @@ system_test(
"@crate_index//:slog",
"@crate_index//:tokio",
],
)
)
4 changes: 4 additions & 0 deletions rs/tests/networking/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ path = "canister_http_stress_test.rs"
name = "ic-systest-canister-http-soak"
path = "canister_http_soak_test.rs"

[[bin]]
name = "ic-systest-canister-http-flexible"
path = "canister_http_flexible_test.rs"

[[bin]]
name = "ic-systest-canister-http"
path = "canister_http_test.rs"
Expand Down
Loading