Skip to main content

chio_kernel/receipt_support/
receipt_scopes.rs

1use std::cell::RefCell;
2use std::collections::VecDeque;
3
4use chio_appraisal::VerifiedRuntimeAttestationRecord;
5use chio_core::capability::governance::GovernedUpstreamCallChainProof;
6use chio_core::receipt::metadata::GuardEvidence;
7
8#[derive(Debug, Clone, Default, PartialEq, Eq)]
9pub(crate) struct GovernedCallChainReceiptEvidence {
10    pub(crate) local_parent_request_id: Option<String>,
11    pub(crate) local_parent_receipt_id: Option<String>,
12    pub(crate) capability_delegator_subject: Option<String>,
13    pub(crate) capability_origin_subject: Option<String>,
14    pub(crate) upstream_proof: Option<GovernedUpstreamCallChainProof>,
15    pub(crate) continuation_token_id: Option<String>,
16    pub(crate) session_anchor_id: Option<String>,
17}
18
19thread_local! {
20    static GOVERNED_CALL_CHAIN_RECEIPT_EVIDENCE: RefCell<Option<GovernedCallChainReceiptEvidence>> =
21        const { RefCell::new(None) };
22    static GOVERNED_RUNTIME_ATTESTATION_RECORD: RefCell<Option<VerifiedRuntimeAttestationRecord>> =
23        const { RefCell::new(None) };
24    static PRE_INVOCATION_GUARD_EVIDENCE: RefCell<Vec<GuardEvidence>> =
25        const { RefCell::new(Vec::new()) };
26    static POST_INVOCATION_GUARD_EVIDENCE: RefCell<Vec<GuardEvidence>> =
27        const { RefCell::new(Vec::new()) };
28    static FIXED_RUNTIME_UNIX_SECS: RefCell<Option<u64>> = const { RefCell::new(None) };
29    static FIXED_RUNTIME_RECEIPT_IDS: RefCell<Option<FixedRuntimeReceiptIds>> =
30        const { RefCell::new(None) };
31}
32
33struct FixedRuntimeReceiptIds {
34    ids: VecDeque<String>,
35    counter: u64,
36}
37
38pub struct FixedRuntimeScope {
39    previous_unix_secs: Option<u64>,
40    previous_receipt_ids: Option<FixedRuntimeReceiptIds>,
41}
42
43impl Drop for FixedRuntimeScope {
44    fn drop(&mut self) {
45        let previous_unix_secs = self.previous_unix_secs.take();
46        FIXED_RUNTIME_UNIX_SECS.with(|slot| {
47            *slot.borrow_mut() = previous_unix_secs;
48        });
49        let previous_receipt_ids = self.previous_receipt_ids.take();
50        FIXED_RUNTIME_RECEIPT_IDS.with(|slot| {
51            *slot.borrow_mut() = previous_receipt_ids;
52        });
53    }
54}
55
56pub fn scope_fixed_runtime_for_current_thread(
57    now_unix_secs: u64,
58    receipt_ids: impl IntoIterator<Item = String>,
59) -> FixedRuntimeScope {
60    let previous_unix_secs = FIXED_RUNTIME_UNIX_SECS.with(|slot| slot.replace(Some(now_unix_secs)));
61    let previous_receipt_ids = FIXED_RUNTIME_RECEIPT_IDS.with(|slot| {
62        slot.replace(Some(FixedRuntimeReceiptIds {
63            ids: receipt_ids.into_iter().collect(),
64            counter: 0,
65        }))
66    });
67    FixedRuntimeScope {
68        previous_unix_secs,
69        previous_receipt_ids,
70    }
71}
72
73pub fn fixed_runtime_unix_secs_for_current_thread() -> Option<u64> {
74    FIXED_RUNTIME_UNIX_SECS.with(|slot| *slot.borrow())
75}
76
77pub(crate) struct ScopedGovernedCallChainReceiptEvidence {
78    previous: Option<GovernedCallChainReceiptEvidence>,
79}
80
81impl Drop for ScopedGovernedCallChainReceiptEvidence {
82    fn drop(&mut self) {
83        let previous = self.previous.take();
84        GOVERNED_CALL_CHAIN_RECEIPT_EVIDENCE.with(|slot| {
85            slot.replace(previous);
86        });
87    }
88}
89
90pub(crate) fn scope_governed_call_chain_receipt_evidence(
91    evidence: Option<GovernedCallChainReceiptEvidence>,
92) -> ScopedGovernedCallChainReceiptEvidence {
93    let previous = GOVERNED_CALL_CHAIN_RECEIPT_EVIDENCE.with(|slot| slot.replace(evidence));
94    ScopedGovernedCallChainReceiptEvidence { previous }
95}
96
97pub(super) fn current_governed_call_chain_receipt_evidence(
98) -> Option<GovernedCallChainReceiptEvidence> {
99    GOVERNED_CALL_CHAIN_RECEIPT_EVIDENCE.with(|slot| slot.borrow().clone())
100}
101
102pub(crate) struct ScopedGovernedRuntimeAttestationRecord {
103    previous: Option<VerifiedRuntimeAttestationRecord>,
104}
105
106impl Drop for ScopedGovernedRuntimeAttestationRecord {
107    fn drop(&mut self) {
108        let previous = self.previous.take();
109        GOVERNED_RUNTIME_ATTESTATION_RECORD.with(|slot| {
110            slot.replace(previous);
111        });
112    }
113}
114
115pub(crate) fn scope_governed_runtime_attestation_receipt_record(
116    record: Option<VerifiedRuntimeAttestationRecord>,
117) -> ScopedGovernedRuntimeAttestationRecord {
118    let previous = GOVERNED_RUNTIME_ATTESTATION_RECORD.with(|slot| slot.replace(record));
119    ScopedGovernedRuntimeAttestationRecord { previous }
120}
121
122pub(super) fn current_governed_runtime_attestation_record(
123) -> Option<VerifiedRuntimeAttestationRecord> {
124    GOVERNED_RUNTIME_ATTESTATION_RECORD.with(|slot| slot.borrow().clone())
125}
126
127pub(crate) struct ScopedPreInvocationGuardEvidence {
128    previous: Vec<GuardEvidence>,
129}
130
131impl Drop for ScopedPreInvocationGuardEvidence {
132    fn drop(&mut self) {
133        let previous = core::mem::take(&mut self.previous);
134        PRE_INVOCATION_GUARD_EVIDENCE.with(|slot| {
135            slot.replace(previous);
136        });
137    }
138}
139
140pub(crate) fn scope_pre_invocation_guard_evidence(
141    evidence: Vec<GuardEvidence>,
142) -> ScopedPreInvocationGuardEvidence {
143    let previous = PRE_INVOCATION_GUARD_EVIDENCE.with(|slot| slot.replace(evidence));
144    ScopedPreInvocationGuardEvidence { previous }
145}
146
147pub(crate) fn current_pre_invocation_guard_evidence() -> Vec<GuardEvidence> {
148    PRE_INVOCATION_GUARD_EVIDENCE.with(|slot| slot.borrow().clone())
149}
150
151pub(crate) struct ScopedPostInvocationGuardEvidence {
152    previous: Vec<GuardEvidence>,
153}
154
155impl Drop for ScopedPostInvocationGuardEvidence {
156    fn drop(&mut self) {
157        let previous = core::mem::take(&mut self.previous);
158        POST_INVOCATION_GUARD_EVIDENCE.with(|slot| {
159            slot.replace(previous);
160        });
161    }
162}
163
164pub(crate) fn scope_post_invocation_guard_evidence(
165    evidence: Vec<GuardEvidence>,
166) -> ScopedPostInvocationGuardEvidence {
167    let previous = POST_INVOCATION_GUARD_EVIDENCE.with(|slot| slot.replace(evidence));
168    ScopedPostInvocationGuardEvidence { previous }
169}
170
171pub(crate) fn current_post_invocation_guard_evidence() -> Vec<GuardEvidence> {
172    POST_INVOCATION_GUARD_EVIDENCE.with(|slot| slot.borrow().clone())
173}
174
175pub(super) fn next_fixed_runtime_receipt_id(prefix: &str) -> Option<String> {
176    FIXED_RUNTIME_RECEIPT_IDS.with(|slot| {
177        let mut fixed = slot.borrow_mut();
178        let fixed = fixed.as_mut()?;
179        if let Some(id) = fixed.ids.pop_front() {
180            return Some(id);
181        }
182        let id = format!("{prefix}-fixed-runtime-{}", fixed.counter);
183        fixed.counter = fixed.counter.saturating_add(1);
184        Some(id)
185    })
186}