1use super::nonactivation::*;
2use super::*;
3
4#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
5#[serde(deny_unknown_fields)]
6pub struct CandidateExclusiveTarget {
7 pub family: CandidateFamilyId,
8 pub domain: CandidateExclusiveObjectDomain,
9 pub semantic_hash: ObjectHash,
10 pub object: ExactObjectRef,
11}
12
13impl CandidateExclusiveTarget {
14 pub(super) fn validate_semantic(&self, bytes: &[u8]) -> Result<(), RemoteObjectRecordError> {
15 match &self.domain {
16 CandidateExclusiveObjectDomain::CircleBootstrapImage { reference, .. }
17 if bytes.is_empty() && self.semantic_hash == reference.image_hash =>
18 {
19 Ok(())
20 }
21 CandidateExclusiveObjectDomain::CircleBootstrapImage { .. } => {
22 Err(RemoteObjectRecordError::StoredReferenceMismatch)
23 }
24 _ => validate_semantic_hash(self.semantic_hash, bytes),
25 }
26 }
27}
28
29#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
30#[serde(rename_all = "snake_case", deny_unknown_fields)]
31pub enum CandidateExclusiveObjectDomain {
32 MergeMembershipEntry {
33 family: CandidateFamilyId,
34 reference: crate::membership::MembershipEntryRef,
35 },
36 MergeMembershipHead {
37 family: CandidateFamilyId,
38 reference: crate::membership::MembershipHeadRef,
39 },
40 MergeMembershipWrappedStoreKey {
41 family: CandidateFamilyId,
42 reference: crate::wrapped_store_key::WrappedStoreKeyRef,
43 },
44 StorePackage {
45 reference: crate::store_commit::StorePackageRef,
46 },
47 CirclePackage {
48 reference: crate::store_commit::CirclePackageRef,
49 },
50 CircleAccessLeaf {
51 family: CandidateFamilyId,
52 circle_id: CircleId,
53 reference: crate::store_commit::CircleAccessLeafObjectRef,
54 },
55 CircleAccessEnvelope {
56 family: CandidateFamilyId,
57 circle_id: CircleId,
58 reference: crate::store_commit::CircleAccessEnvelopeObjectRef,
59 },
60 CircleEpochCloseIntent {
61 family: CandidateFamilyId,
62 circle_id: CircleId,
63 reference: crate::circle_control::CircleEpochCloseIntentRef,
64 },
65 CircleEpochCloseOutcome {
66 family: CandidateFamilyId,
67 circle_id: CircleId,
68 reference: crate::circle_control::CircleEpochCloseOutcomeRef,
69 },
70 CircleEpochCloseCancellation {
71 family: CandidateFamilyId,
72 circle_id: CircleId,
73 reference: crate::circle_control::CircleEpochCloseCancellationRef,
74 },
75 CircleBootstrapImage {
76 family: CandidateFamilyId,
77 circle_id: CircleId,
78 owner_pubkey: String,
79 epoch_id: crate::circle::CircleEpochId,
80 recipient_slot: String,
81 reference: crate::store_commit::SnapshotImageRef,
82 },
83}
84
85impl CandidateExclusiveObjectDomain {
86 pub(super) fn family(&self) -> CandidateFamilyId {
87 match self {
88 Self::MergeMembershipEntry { family, .. }
89 | Self::MergeMembershipHead { family, .. }
90 | Self::MergeMembershipWrappedStoreKey { family, .. } => *family,
91 Self::StorePackage { reference } => reference.candidate_family,
92 Self::CirclePackage { reference } => reference.package.candidate_family,
93 Self::CircleAccessLeaf { family, .. }
94 | Self::CircleAccessEnvelope { family, .. }
95 | Self::CircleEpochCloseIntent { family, .. }
96 | Self::CircleEpochCloseOutcome { family, .. }
97 | Self::CircleEpochCloseCancellation { family, .. }
98 | Self::CircleBootstrapImage { family, .. } => *family,
99 }
100 }
101
102 pub(super) fn object(&self) -> &ExactObjectRef {
103 match self {
104 Self::MergeMembershipEntry { reference, .. } => &reference.object,
105 Self::MergeMembershipHead { reference, .. } => &reference.object,
106 Self::MergeMembershipWrappedStoreKey { reference, .. } => &reference.object,
107 Self::StorePackage { reference } => &reference.object,
108 Self::CirclePackage { reference } => &reference.package.object,
109 Self::CircleAccessLeaf { reference, .. } => &reference.object,
110 Self::CircleAccessEnvelope { reference, .. } => &reference.object,
111 Self::CircleEpochCloseIntent { reference, .. } => &reference.object,
112 Self::CircleEpochCloseOutcome { reference, .. } => &reference.object,
113 Self::CircleEpochCloseCancellation { reference, .. } => &reference.object,
114 Self::CircleBootstrapImage { reference, .. } => &reference.object,
115 }
116 }
117
118 pub fn shared_destination(&self) -> Option<SharedLiveSetObjectDomain> {
119 match self {
120 Self::StorePackage { reference } => Some(SharedLiveSetObjectDomain::StorePackage {
121 reference: reference.clone(),
122 }),
123 Self::CirclePackage { reference } => Some(SharedLiveSetObjectDomain::CirclePackage {
124 reference: reference.clone(),
125 }),
126 Self::CircleBootstrapImage { reference, .. } => {
127 Some(SharedLiveSetObjectDomain::CircleBootstrapImage {
128 reference: reference.clone(),
129 })
130 }
131 Self::MergeMembershipEntry { .. }
132 | Self::MergeMembershipHead { .. }
133 | Self::MergeMembershipWrappedStoreKey { .. }
134 | Self::CircleAccessLeaf { .. }
135 | Self::CircleAccessEnvelope { .. }
136 | Self::CircleEpochCloseIntent { .. }
137 | Self::CircleEpochCloseOutcome { .. }
138 | Self::CircleEpochCloseCancellation { .. } => None,
139 }
140 }
141
142 pub fn retained_destination(&self) -> Option<RetainedAuthorityObjectDomain> {
143 match self {
144 Self::MergeMembershipEntry { reference, .. } => {
145 Some(RetainedAuthorityObjectDomain::MergeMembershipEntry {
146 reference: reference.clone(),
147 })
148 }
149 Self::MergeMembershipHead { reference, .. } => {
150 Some(RetainedAuthorityObjectDomain::MergeMembershipHead {
151 reference: reference.clone(),
152 })
153 }
154 Self::MergeMembershipWrappedStoreKey { reference, .. } => Some(
155 RetainedAuthorityObjectDomain::MergeMembershipWrappedStoreKey {
156 reference: reference.clone(),
157 },
158 ),
159 Self::CircleAccessLeaf {
160 family,
161 circle_id,
162 reference,
163 } => Some(RetainedAuthorityObjectDomain::CircleAccessLeaf {
164 family: *family,
165 circle_id: *circle_id,
166 reference: reference.clone(),
167 }),
168 Self::CircleAccessEnvelope {
169 family,
170 circle_id,
171 reference,
172 } => Some(RetainedAuthorityObjectDomain::CircleAccessEnvelope {
173 family: *family,
174 circle_id: *circle_id,
175 reference: reference.clone(),
176 }),
177 Self::CircleEpochCloseIntent {
178 family,
179 circle_id,
180 reference,
181 } => Some(RetainedAuthorityObjectDomain::CircleEpochCloseIntent {
182 family: *family,
183 circle_id: *circle_id,
184 reference: reference.clone(),
185 }),
186 Self::CircleEpochCloseOutcome {
187 family,
188 circle_id,
189 reference,
190 } => Some(RetainedAuthorityObjectDomain::CircleEpochCloseOutcome {
191 family: *family,
192 circle_id: *circle_id,
193 reference: reference.clone(),
194 }),
195 Self::CircleEpochCloseCancellation {
196 family,
197 circle_id,
198 reference,
199 } => Some(
200 RetainedAuthorityObjectDomain::CircleEpochCloseCancellation {
201 family: *family,
202 circle_id: *circle_id,
203 reference: reference.clone(),
204 },
205 ),
206 Self::StorePackage { .. }
207 | Self::CirclePackage { .. }
208 | Self::CircleBootstrapImage { .. } => None,
209 }
210 }
211}
212
213impl SharedLiveSetObjectDomain {
214 pub(super) fn package_object(&self) -> Result<&ExactObjectRef, RemoteObjectRecordError> {
215 match self {
216 Self::StoredBlob
217 | Self::StoreSnapshotImage { .. }
218 | Self::StoreMembershipRollup { .. }
219 | Self::CircleBootstrapImage { .. } => Err(RemoteObjectRecordError::DomainMismatch),
220 Self::StorePackage { reference } => Ok(&reference.object),
221 Self::CirclePackage { reference } => Ok(&reference.package.object),
222 }
223 }
224}
225
226#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
227#[serde(deny_unknown_fields)]
228pub struct SharedLiveSetObjectRef {
229 pub domain: SharedLiveSetObjectDomain,
230 pub semantic_hash: ObjectHash,
231 pub object: ExactObjectRef,
232}
233
234impl SharedLiveSetObjectRef {
235 pub(super) fn validate_semantic(&self, bytes: &[u8]) -> Result<(), RemoteObjectRecordError> {
236 match &self.domain {
237 SharedLiveSetObjectDomain::StoreSnapshotImage { reference }
238 if bytes.is_empty()
239 && self.semantic_hash == reference.image_hash
240 && self.object == reference.object =>
241 {
242 Ok(())
243 }
244 SharedLiveSetObjectDomain::StoreSnapshotImage { .. } => {
245 Err(RemoteObjectRecordError::StoredReferenceMismatch)
246 }
247 SharedLiveSetObjectDomain::CircleBootstrapImage { reference }
248 if bytes.is_empty()
249 && self.semantic_hash == reference.image_hash
250 && self.object == reference.object =>
251 {
252 Ok(())
253 }
254 SharedLiveSetObjectDomain::CircleBootstrapImage { .. } => {
255 Err(RemoteObjectRecordError::StoredReferenceMismatch)
256 }
257 SharedLiveSetObjectDomain::StoreMembershipRollup { reference }
260 if bytes.is_empty()
261 && self.semantic_hash == reference.rollup_hash
262 && self.object == reference.object =>
263 {
264 Ok(())
265 }
266 SharedLiveSetObjectDomain::StoreMembershipRollup { .. } => {
267 Err(RemoteObjectRecordError::StoredReferenceMismatch)
268 }
269 _ => validate_semantic_hash(self.semantic_hash, bytes),
270 }
271 }
272}
273
274#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
275#[serde(rename_all = "snake_case", deny_unknown_fields)]
276pub enum SharedLiveSetObjectDomain {
277 StoredBlob,
278 StoreSnapshotImage {
279 reference: crate::store_commit::SnapshotImageRef,
280 },
281 StoreMembershipRollup {
285 reference: crate::store_commit::MembershipRollupRef,
286 },
287 CircleBootstrapImage {
288 reference: crate::store_commit::SnapshotImageRef,
289 },
290 StorePackage {
291 reference: crate::store_commit::StorePackageRef,
292 },
293 CirclePackage {
294 reference: crate::store_commit::CirclePackageRef,
295 },
296}
297
298#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
299#[serde(deny_unknown_fields)]
300pub struct RetainedAuthorityObjectRef {
301 pub domain: RetainedAuthorityObjectDomain,
302 pub semantic_hash: ObjectHash,
303 pub object: ExactObjectRef,
304}
305
306#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
307#[serde(deny_unknown_fields)]
308pub struct ProtocolInertObject {
309 pub identity: RetainedAuthorityObjectRef,
310 pub(crate) former_candidates: Vec<CandidateNonactivation>,
311}
312
313impl ProtocolInertObject {
314 pub(super) fn new(
315 identity: RetainedAuthorityObjectRef,
316 former_candidates: Vec<CandidateNonactivation>,
317 ) -> Result<Self, RemoteObjectRecordError> {
318 let value = Self {
319 identity,
320 former_candidates,
321 };
322 value.validate()?;
323 Ok(value)
324 }
325
326 pub fn object_id(&self) -> ObjectHash {
327 remote_object_id(&self.identity.object)
328 }
329
330 pub fn validate(&self) -> Result<(), RemoteObjectRecordError> {
331 validate_nonactivations(&self.former_candidates)
332 }
333}
334
335impl RetainedAuthorityObjectRef {
336 pub(super) fn validate_semantic(&self, bytes: &[u8]) -> Result<(), RemoteObjectRecordError> {
337 validate_semantic_hash(self.semantic_hash, bytes)
338 }
339}
340
341#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
342#[serde(rename_all = "snake_case", deny_unknown_fields)]
343pub enum RetainedAuthorityObjectDomain {
344 Commit {
345 reference: StoreBatchCommitRef,
346 },
347 Acknowledgement {
348 reference: crate::store_commit::StoreAckRef,
349 },
350 CircleAcknowledgement {
351 reference: CircleAckRef,
352 },
353 MergeMembershipWrappedStoreKey {
354 reference: crate::wrapped_store_key::WrappedStoreKeyRef,
355 },
356
357 ProviderAccessGrant {
358 reference: crate::provider::StoreMemberProviderAccessGrantRef,
359 },
360 DeviceJoinAbandonment {
361 reference: crate::store_commit::DeviceJoinAbandonmentRef,
362 },
363 DeviceRegistration {
364 reference: crate::store_commit::StoreDeviceRegistrationRef,
365 },
366 MergeMembershipEntry {
367 reference: crate::membership::MembershipEntryRef,
368 },
369 MergeMembershipHead {
370 reference: crate::membership::MembershipHeadRef,
371 },
372 MembershipHeadAcceptance {
373 head: crate::membership::MembershipHeadRef,
374 publication: crate::store_commit::StorePublicationRef,
375 },
376 OwnerPromotionRequestPublication {
377 promotion_id: crate::store_commit::OwnerPromotionId,
378 activation: crate::store_commit::OwnerPromotionRequestActivation,
379 },
380 DeviceExclusionProposal {
381 reference: crate::store_commit::StoreDeviceExclusionProposalRef,
382 },
383 DeviceExclusionOutcome {
384 reference: crate::store_commit::StoreDeviceExclusionOutcomeRef,
385 },
386 ReclaimEvidence {
387 reference: crate::reclaim::ReclaimEvidenceRef,
388 },
389 ReclaimAuthorization {
390 reference: crate::reclaim::ReclaimAuthorizationRef,
391 },
392 ReclaimReceipt {
393 reference: crate::reclaim::ReclaimReceiptRef,
394 },
395 CircleAccessLeaf {
396 family: CandidateFamilyId,
397 circle_id: CircleId,
398 reference: crate::store_commit::CircleAccessLeafObjectRef,
399 },
400 CircleAccessEnvelope {
401 family: CandidateFamilyId,
402 circle_id: CircleId,
403 reference: crate::store_commit::CircleAccessEnvelopeObjectRef,
404 },
405 CircleEpochCloseIntent {
406 family: CandidateFamilyId,
407 circle_id: CircleId,
408 reference: crate::circle_control::CircleEpochCloseIntentRef,
409 },
410 CircleEpochCloseOutcome {
411 family: CandidateFamilyId,
412 circle_id: CircleId,
413 reference: crate::circle_control::CircleEpochCloseOutcomeRef,
414 },
415 CircleEpochCloseCancellation {
416 family: CandidateFamilyId,
417 circle_id: CircleId,
418 reference: crate::circle_control::CircleEpochCloseCancellationRef,
419 },
420}