chio_kernel/receipt_support/
receipt_scopes.rs1use 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}