canic-core 0.110.35

Canic — a canister orchestration and management toolkit for the Internet Computer
Documentation
use super::FleetSubnetRootDrainingReservationOps;
use crate::{
    dto::fleet_registry::{
        FleetRegistryVersion, FleetSubnetRootDrainingReservationRequest,
        FleetSubnetRootDrainingReservationResponse, FleetSubnetRootEntry, FleetSubnetRootStatus,
    },
    ids::{
        AppId, CanonicalNetworkId, ComponentTopologyDigest, CyclesFundingBudget, FleetBinding,
        FleetCoordinatorBinding, FleetId, FleetKey, FleetRegistryAuthority,
        FleetSubnetCanisterPoolConfig, FleetSubnetRootLimits, FleetSubnetRootReleaseSet,
        ReleaseBuildId, ReleaseBuildNonce, ReleaseSetDigest, SubnetId,
    },
};
use candid::Principal;

#[test]
fn reservation_hash_is_domain_separated_and_excludes_only_its_hash_field() {
    let mut response = fixture();
    let hash = FleetSubnetRootDrainingReservationOps::content_hash(&response)
        .expect("hash draining reservation");
    assert_eq!(
        crate::cdk::utils::hash::hex_bytes(hash),
        "5c97a41797c3f5d714d8a7aac4ed61280cc3d3320d8ec59fe153e31c7be9a999"
    );
    response.reservation_hash = [99; 32];
    assert_eq!(
        FleetSubnetRootDrainingReservationOps::content_hash(&response)
            .expect("rehash draining reservation"),
        hash
    );

    let mut redirected = response.clone();
    redirected.request.asset_recipient = Principal::from_slice(&[16; 29]);
    assert_ne!(
        FleetSubnetRootDrainingReservationOps::content_hash(&redirected)
            .expect("hash redirected draining reservation"),
        hash
    );

    response.prepared_at_ns += 1;
    assert_ne!(
        FleetSubnetRootDrainingReservationOps::content_hash(&response)
            .expect("hash changed draining reservation"),
        hash
    );
}

fn fixture() -> FleetSubnetRootDrainingReservationResponse {
    let coordinator = Principal::from_slice(&[3; 29]);
    let authority = FleetRegistryAuthority {
        binding: FleetCoordinatorBinding {
            fleet: FleetBinding {
                fleet: FleetKey {
                    canonical_network_id: CanonicalNetworkId::ic_mainnet(),
                    fleet_id: FleetId::from_generated_bytes([1; 32]),
                },
                app: AppId::from("test"),
            },
            coordinator_subnet: SubnetId::from_principal(Principal::from_slice(&[2; 29])),
            coordinator,
        },
        epoch: 1,
    };
    let expected_registry = FleetRegistryVersion {
        authority,
        revision: 7,
        content_hash: [4; 32],
    };
    FleetSubnetRootDrainingReservationResponse {
        request: FleetSubnetRootDrainingReservationRequest {
            asset_recipient: expected_registry.authority.binding.coordinator,
            operation_id: [5; 32],
            expected_registry,
            expected_root: FleetSubnetRootEntry {
                fleet_subnet_root: Principal::from_slice(&[6; 29]),
                placement_subnet: SubnetId::from_principal(Principal::from_slice(&[7; 29])),
                status: FleetSubnetRootStatus::Active,
                component_admissions: Vec::new(),
                component_topology_digest: ComponentTopologyDigest::from_bytes([8; 32]),
                active_release_set: FleetSubnetRootReleaseSet {
                    release_build_id: ReleaseBuildId::from_nonce(
                        ReleaseBuildNonce::from_random_bytes([9; 32]),
                    ),
                    manifest_digest: ReleaseSetDigest::from_bytes([10; 32]),
                },
                limits: FleetSubnetRootLimits {
                    maximum_component_instances: 11,
                    maximum_registry_bytes: 12,
                    maximum_wasm_store_bytes: 13,
                    canister_pool: FleetSubnetCanisterPoolConfig {
                        minimum_size: 1,
                        maximum_size: 2,
                        canister_cycles: crate::cdk::types::Cycles::new(1_000_000_000_000),
                        creation_execution_margin: crate::cdk::types::Cycles::new(
                            1_000_000_000_000,
                        ),
                    },
                    cycles_funding: CyclesFundingBudget {
                        window_secs: 3_600,
                        maximum_cycles: crate::cdk::types::Cycles::new(2_000_000_000_000),
                    },
                    maximum_group_placements: 14,
                },
                funding: crate::test::support::fleet_subnet_root_funding_authority(),
            },
        },
        coordinator,
        prepared_at_ns: 15,
        reservation_hash: [0; 32],
    }
}