chio-kernel 0.1.2

Chio runtime kernel: capability validation, guard evaluation, receipt signing
Documentation
use chio_core::capability::governance::{MeteredBillingContext, MeteredSettlementMode};

use crate::KernelError;

const BILLING_UNIT: &str = "verified_outcome";

pub(super) fn validate_verified_outcome_request(
    metered: &MeteredBillingContext,
) -> Result<(), KernelError> {
    let is_outcome = metered.quote.billing_unit == BILLING_UNIT;
    let Some(request) = metered.verified_outcome.as_ref() else {
        return if is_outcome {
            deny("verified outcome billing requires its typed request extension")
        } else {
            Ok(())
        };
    };
    if !is_outcome {
        return deny("verified outcome request extension is forbidden for another billing unit");
    }
    if metered.settlement_mode != MeteredSettlementMode::HoldCapture {
        return deny("verified outcome billing requires hold_capture settlement");
    }
    if metered.quote.quoted_units != 1 || metered.max_billed_units.is_some_and(|units| units != 1) {
        return deny("verified outcome billing requires exactly one quoted unit");
    }
    if request.validate().is_err() {
        return deny("verified outcome request is invalid");
    }
    deny("verified outcome pricing is not activated")
}

fn deny<T>(reason: &str) -> Result<T, KernelError> {
    Err(KernelError::GovernedTransactionDenied(reason.to_owned()))
}

#[cfg(test)]
mod tests {
    use chio_core::capability::governance::{
        VerifiedOutcomeRequestV1, VERIFIED_OUTCOME_REQUEST_SCHEMA,
    };
    use chio_core::capability::scope::MonetaryAmount;

    use super::*;

    fn extension() -> VerifiedOutcomeRequestV1 {
        VerifiedOutcomeRequestV1 {
            schema: VERIFIED_OUTCOME_REQUEST_SCHEMA.to_owned(),
            listing_id: "listing-1".to_owned(),
            listing_digest: "1".repeat(64),
            provider_binding_digest: "2".repeat(64),
            pricing_id: "3".repeat(64),
            pricing_digest: "4".repeat(64),
            predicate_id: "5".repeat(64),
            predicate_digest: "6".repeat(64),
            sla_digest: Some("7".repeat(64)),
            receiver_binding_digest: "8".repeat(64),
        }
    }

    fn context() -> MeteredBillingContext {
        MeteredBillingContext {
            settlement_mode: MeteredSettlementMode::HoldCapture,
            quote: chio_core::capability::governance::MeteredBillingQuote {
                quote_id: "quote-1".to_owned(),
                provider: "provider-1".to_owned(),
                billing_unit: BILLING_UNIT.to_owned(),
                quoted_units: 1,
                quoted_cost: MonetaryAmount {
                    units: 500,
                    currency: "USD".to_owned(),
                },
                issued_at: 1,
                expires_at: Some(2),
            },
            max_billed_units: Some(1),
            verified_outcome: Some(extension()),
        }
    }

    fn reason(context: &MeteredBillingContext) -> String {
        match validate_verified_outcome_request(context) {
            Err(KernelError::GovernedTransactionDenied(reason)) => reason,
            other => panic!("unexpected validation result: {other:?}"),
        }
    }

    #[test]
    fn inactive_contract_rejects_every_outcome_request_shape() {
        let mut missing = context();
        missing.verified_outcome = None;
        assert!(reason(&missing).contains("requires its typed request extension"));

        let mut foreign = context();
        foreign.quote.billing_unit = "tokens".to_owned();
        assert!(reason(&foreign).contains("forbidden for another billing unit"));

        let mut prepaid = context();
        prepaid.settlement_mode = MeteredSettlementMode::MustPrepay;
        assert!(reason(&prepaid).contains("requires hold_capture"));

        let mut multiple = context();
        multiple.quote.quoted_units = 2;
        assert!(reason(&multiple).contains("exactly one quoted unit"));

        let mut unknown = context();
        let Some(request) = unknown.verified_outcome.as_mut() else {
            panic!("verified outcome request is missing");
        };
        request.schema = "chio.outcome.request.v9".to_owned();
        assert!(reason(&unknown).contains("request is invalid"));

        let mut empty = context();
        let Some(request) = empty.verified_outcome.as_mut() else {
            panic!("verified outcome request is missing");
        };
        request.listing_id.clear();
        assert!(reason(&empty).contains("request is invalid"));

        let mut malformed = context();
        let Some(request) = malformed.verified_outcome.as_mut() else {
            panic!("verified outcome request is missing");
        };
        request.pricing_digest = "A".repeat(64);
        assert!(reason(&malformed).contains("request is invalid"));

        assert!(reason(&context()).contains("pricing is not activated"));
    }

    #[test]
    fn unrelated_metered_billing_remains_admissible() {
        let mut unrelated = context();
        unrelated.quote.billing_unit = "tokens".to_owned();
        unrelated.verified_outcome = None;
        assert!(validate_verified_outcome_request(&unrelated).is_ok());
    }
}