canic-core 0.25.2

Canic — a canister orchestration and management toolkit for the Internet Computer
Documentation
use crate::{
    dto::{
        auth::{DelegationRequest, RoleAttestationRequest},
        rpc::RootRequestMetadata,
    },
    ops::ic::IcOps,
};
use sha2::{Digest, Sha256};
use std::sync::atomic::{AtomicU64, Ordering};

const DEFAULT_ROOT_REQUEST_TTL_SECONDS: u64 = 300;
static ROOT_REQUEST_NONCE: AtomicU64 = AtomicU64::new(1);

pub(super) fn with_root_request_metadata(mut request: DelegationRequest) -> DelegationRequest {
    if request.metadata.is_none() {
        request.metadata = Some(new_request_metadata());
    }
    request
}

pub(super) fn with_root_attestation_request_metadata(
    mut request: RoleAttestationRequest,
) -> RoleAttestationRequest {
    if request.metadata.is_none() {
        request.metadata = Some(new_request_metadata());
    }
    request
}

fn new_request_metadata() -> RootRequestMetadata {
    RootRequestMetadata {
        request_id: generate_request_id(),
        ttl_seconds: DEFAULT_ROOT_REQUEST_TTL_SECONDS,
    }
}

fn generate_request_id() -> [u8; 32] {
    let nonce = ROOT_REQUEST_NONCE.fetch_add(1, Ordering::Relaxed);
    let now = IcOps::now_secs();
    let caller = IcOps::metadata_entropy_caller();
    let canister = IcOps::metadata_entropy_canister();

    let mut hasher = Sha256::new();
    hasher.update(now.to_be_bytes());
    hasher.update(nonce.to_be_bytes());
    hasher.update(caller.as_slice());
    hasher.update(canister.as_slice());
    hasher.finalize().into()
}