Skip to content

Commit

Permalink
fix(execution): Include bitcoin canisters as aliases for IC_00 routing
Browse files Browse the repository at this point in the history
  • Loading branch information
dsarlis committed Jan 18, 2024
1 parent 6b5656b commit 97e4d6a
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 7 deletions.
108 changes: 103 additions & 5 deletions rs/execution_environment/src/execution_environment/tests.rs
Expand Up @@ -9,10 +9,11 @@ use ic_types::nominal_cycles::NominalCycles;
use ic_base_types::{NumBytes, NumSeconds};
use ic_error_types::{ErrorCode, RejectCode, UserError};
use ic_ic00_types::{
self as ic00, BoundedHttpHeaders, CanisterChange, CanisterHttpRequestArgs, CanisterIdRecord,
CanisterStatusResultV2, CanisterStatusType, DerivationPath, EcdsaCurve, EcdsaKeyId, EmptyBlob,
HttpMethod, Method, Payload as Ic00Payload, ProvisionalCreateCanisterWithCyclesArgs,
ProvisionalTopUpCanisterArgs, TransformContext, TransformFunc, IC_00,
self as ic00, BitcoinGetUtxosArgs, BitcoinNetwork, BoundedHttpHeaders, CanisterChange,
CanisterHttpRequestArgs, CanisterIdRecord, CanisterStatusResultV2, CanisterStatusType,
DerivationPath, EcdsaCurve, EcdsaKeyId, EmptyBlob, HttpMethod, Method, Payload as Ic00Payload,
ProvisionalCreateCanisterWithCyclesArgs, ProvisionalTopUpCanisterArgs, TransformContext,
TransformFunc, IC_00,
};
use ic_registry_routing_table::canister_id_into_u64;
use ic_registry_routing_table::CanisterIdRange;
Expand Down Expand Up @@ -2451,8 +2452,67 @@ fn canister_output_queue_does_not_overflow_when_calling_ic00() {
call_args().other_side(args.clone()),
)
.build();
test.ingress_raw(uc, "update", payload);
let (message_id, _) = test.ingress_raw(uc, "update", payload);
test.execute_message(uc);
if i > DEFAULT_QUEUE_CAPACITY {
assert_eq!(
test.ingress_state(&message_id),
IngressState::Failed(UserError::new(
ErrorCode::CanisterCalledTrap,
format!("Canister {} trapped explicitly: call_perform failed", uc)
))
);
} else {
assert_eq!(test.ingress_state(&message_id), IngressState::Processing);
}
let system_state = &mut test.canister_state_mut(uc).system_state;
assert_eq!(1, system_state.queues().output_queues_len());
assert_eq!(
i.min(DEFAULT_QUEUE_CAPACITY),
system_state.queues().output_message_count()
);
}
}

fn send_messages_to_bitcoin_canister_until_capacity(
test: &mut ExecutionTest,
bitcoin_canister: CanisterId,
network: BitcoinNetwork,
) {
let uc = test.universal_canister().unwrap();

for i in 1..=2 * DEFAULT_QUEUE_CAPACITY {
let target = if i < DEFAULT_QUEUE_CAPACITY / 2 {
bitcoin_canister.get()
} else {
ic00::IC_00.get()
};
let args = Encode!(&BitcoinGetUtxosArgs {
network: network.into(),
address: String::from(""),
filter: None,
})
.unwrap();
let payload = wasm()
.call_simple(
target,
Method::BitcoinGetUtxos,
call_args().other_side(args.clone()),
)
.build();
let (message_id, _) = test.ingress_raw(uc, "update", payload);
test.execute_message(uc);
if i > DEFAULT_QUEUE_CAPACITY {
assert_eq!(
test.ingress_state(&message_id),
IngressState::Failed(UserError::new(
ErrorCode::CanisterCalledTrap,
format!("Canister {} trapped explicitly: call_perform failed", uc)
))
);
} else {
assert_eq!(test.ingress_state(&message_id), IngressState::Processing);
}
let system_state = &mut test.canister_state_mut(uc).system_state;
assert_eq!(1, system_state.queues().output_queues_len());
assert_eq!(
Expand All @@ -2462,6 +2522,44 @@ fn canister_output_queue_does_not_overflow_when_calling_ic00() {
}
}

#[test]
fn canister_output_queue_does_not_overflow_when_calling_bitcoin_mainnet_canister() {
let own_subnet = subnet_test_id(1);
let bitcoin_mainnet_canister = canister_test_id(1);
let mut test = ExecutionTestBuilder::new()
.with_own_subnet_id(own_subnet)
.with_nns_subnet_id(own_subnet)
.with_initial_canister_cycles(1_000_000_000_000_000_000)
.with_bitcoin_mainnet_canister_id(Some(bitcoin_mainnet_canister))
.with_manual_execution()
.build();

send_messages_to_bitcoin_canister_until_capacity(
&mut test,
bitcoin_mainnet_canister,
BitcoinNetwork::Mainnet,
);
}

#[test]
fn canister_output_queue_does_not_overflow_when_calling_bitcoin_testnet_canister() {
let own_subnet = subnet_test_id(1);
let bitcoin_testnet_canister = canister_test_id(1);
let mut test = ExecutionTestBuilder::new()
.with_own_subnet_id(own_subnet)
.with_nns_subnet_id(own_subnet)
.with_initial_canister_cycles(1_000_000_000_000_000_000)
.with_bitcoin_testnet_canister_id(Some(bitcoin_testnet_canister))
.with_manual_execution()
.build();

send_messages_to_bitcoin_canister_until_capacity(
&mut test,
bitcoin_testnet_canister,
BitcoinNetwork::Testnet,
);
}

#[test]
fn can_refund_cycles_after_successful_provisional_create_canister() {
let mut test = ExecutionTestBuilder::new()
Expand Down
11 changes: 9 additions & 2 deletions rs/system_api/src/sandbox_safe_system_state.rs
Expand Up @@ -630,13 +630,20 @@ impl SandboxSafeSystemState {
let available_request_slots = system_state.available_output_request_slots();

// Compute the available slots for IC_00 requests as the minimum of available
// slots across any queue to a subnet explicitly or IC_00 itself.
// slots across any queue to a subnet explicitly, the bitcoin canisters or
// IC_00 itself.
let mut ic00_aliases: BTreeSet<CanisterId> = network_topology
.subnets
.keys()
.map(|id| CanisterId::unchecked_from_principal(id.get()))
.collect();
ic00_aliases.insert(CanisterId::ic_00());
if let Some(bitcoin_testnet_canister_id) = network_topology.bitcoin_testnet_canister_id {
ic00_aliases.insert(bitcoin_testnet_canister_id);
}
if let Some(bitcoin_mainnet_canister_id) = network_topology.bitcoin_mainnet_canister_id {
ic00_aliases.insert(bitcoin_mainnet_canister_id);
}
let ic00_available_request_slots = ic00_aliases
.iter()
.map(|id| {
Expand Down Expand Up @@ -928,7 +935,7 @@ impl SandboxSafeSystemState {
Err(_) => return Err(msg),
};

// If the request is targeted to IC_00 or one of the known subnets
// If the request is targeted to any of the known aliases of IC_00,
// count it towards the available slots for IC_00 requests.
if self.ic00_aliases.contains(&msg.receiver) {
if self.ic00_available_request_slots == 0 {
Expand Down

0 comments on commit 97e4d6a

Please sign in to comment.