coven_protocol/
store_commit.rs1use std::collections::BTreeMap;
4use std::collections::BTreeSet;
5use std::fmt;
6use std::str::FromStr;
7
8use serde::{Deserialize, Serialize};
9
10use super::membership::{
11 verify_membership_entry, AuthorHead, AuthorStreamId, MembershipCoord, MembershipEntry,
12 MembershipEntryRef, MembershipGrantId, MembershipHeadRef, StoreAuthorityChange,
13};
14use crate::circle::{
15 AccessLeafId, CircleBootstrapCoverageRef, CircleBootstrapRef, CircleControlCoord,
16 CircleEpochId, CircleId, CircleMetadataCoord, CircleMetadataHeadRef,
17 CircleRosterConflictResolutionRef, CircleRosterCoord, CircleRosterHeadRef,
18};
19use crate::circle_control::StoreMembershipStateRef;
20use crate::objects::ObjectSlot;
21use crate::objects::{ExactObjectRef, ProviderDeviceBinding};
22use crate::write::WriteId;
23use coven_keys::encryption::KeyFingerprint;
24use coven_keys::keys::{self, UserKeypair};
25
26mod ack_snapshot;
27mod batch_commit;
28mod circle_ack;
29mod circle_snapshot;
30mod device_join;
31pub mod device_join_exchange;
32pub mod device_join_journal;
33mod device_state;
34mod identifiers;
35mod membership_rollup;
36mod operation_refs;
37mod owner_promotion_publication;
38mod packages;
39mod protocol_root;
40mod publication;
41mod reclaim_state;
42mod registration;
43pub use reclaim_state::{
44 RetainedPackageActivation, RetainedReclaimAuthorization, RetainedReclaimState,
45 RetainedStoreSnapshotOwnership,
46};
47mod retained_history;
48mod signed;
49mod validation;
50
51pub use ack_snapshot::*;
52pub use batch_commit::*;
53pub use circle_ack::*;
54pub use circle_snapshot::*;
55pub use device_join::*;
56pub use device_state::*;
57pub use identifiers::*;
58pub use membership_rollup::*;
59pub use owner_promotion_publication::*;
60pub use packages::*;
61pub use protocol_root::*;
62pub use publication::*;
63pub use registration::*;
64pub use retained_history::*;
65pub use signed::{Signed, SignedBody};
66pub use validation::*;
67
68mod ordered_map_entries {
69 use std::collections::BTreeMap;
70
71 use serde::{Deserialize, Deserializer, Serialize, Serializer};
72
73 pub(super) fn serialize<K, V, S>(map: &BTreeMap<K, V>, serializer: S) -> Result<S::Ok, S::Error>
74 where
75 K: Ord + Serialize,
76 V: Serialize,
77 S: Serializer,
78 {
79 map.iter().collect::<Vec<_>>().serialize(serializer)
80 }
81
82 pub(super) fn deserialize<'de, K, V, D>(deserializer: D) -> Result<BTreeMap<K, V>, D::Error>
83 where
84 K: Ord + Deserialize<'de>,
85 V: Deserialize<'de>,
86 D: Deserializer<'de>,
87 {
88 let entries = Vec::<(K, V)>::deserialize(deserializer)?;
89 let entry_count = entries.len();
90 let map = entries.into_iter().collect::<BTreeMap<_, _>>();
91 if map.len() != entry_count {
92 return Err(serde::de::Error::custom(
93 "ordered map entries contain a duplicate key",
94 ));
95 }
96 Ok(map)
97 }
98}
99
100pub const STORE_PROTOCOL_VERSION: u32 = 3;
101
102pub(crate) const STORE_PROTOCOL_ROOT_SEMANTIC_PATH: &str = "store-v1/store-protocol-root";
103#[cfg(any(test, feature = "test-utils"))]
104pub const STORE_PROTOCOL_ROOT_LOGICAL_KEY: &str = "store-v1/store-protocol-root.json";
105pub(crate) const STORE_CANDIDATE_PREFIX: &str = "store-v1/candidates/";
106pub(crate) const STORE_ACK_PREFIX: &str = "store-v1/acks/";
107pub(crate) const STORE_DEVICE_REGISTRATION_PREFIX: &str = "store-v1/devices/";
108pub(crate) const STORE_DEVICE_JOIN_ABANDONMENT_PREFIX: &str = "store-v1/device-join-abandonments/";
109pub(crate) const STORE_DEVICE_JOIN_CLEANUP_RECEIPT_PREFIX: &str =
110 "store-v1/device-join-cleanup-receipts/";
111pub(crate) const STORE_DEVICE_EXCLUSION_PROPOSAL_PREFIX: &str =
112 "store-v1/device-exclusion-proposals/";
113pub(crate) const STORE_DEVICE_EXCLUSION_OUTCOME_PREFIX: &str =
114 "store-v1/device-exclusion-outcomes/";
115pub(crate) const STORE_PROVIDER_ACCESS_GRANT_PREFIX: &str = "store-v1/provider-access/grants/";
116pub(crate) const STORE_OWNER_RECOVERY_PREFIX: &str = "store-v1/recovery/";
117pub(crate) const STORE_SNAPSHOT_META_PREFIX: &str = "store-v1/snapshots/";
118pub(crate) const STORE_SNAPSHOT_IMAGE_PREFIX: &str = "store-v1/snapshot-images/";
119pub(crate) const STORE_MEMBERSHIP_ENTRY_PREFIX: &str = "store-v1/membership/entries/";
120pub(crate) const STORE_MEMBERSHIP_HEAD_PREFIX: &str = "store-v1/membership/heads/";
121pub(crate) const STORE_MEMBERSHIP_ROLLUP_PREFIX: &str = "store-v1/membership-rollups/";
122
123const STORE_PROTOCOL_ROOT_DOMAIN: &[u8] = b"coven.store-protocol-root.v1\0";
124const COMMIT_DOMAIN: &[u8] = b"coven.store-batch-commit.v1\0";
125const REGISTRATION_DOMAIN: &[u8] = b"coven.store-device-registration.v1\0";
126const DEVICE_READINESS_DOMAIN: &[u8] = b"coven.device-readiness.v1\0";
127const DEVICE_EXCLUSION_PROPOSAL_DOMAIN: &[u8] = b"coven.store-device-exclusion-proposal.v1\0";
128const DEVICE_EXCLUSION_DOMAIN: &[u8] = b"coven.store-device-exclusion.v1\0";
129const DEVICE_EXCLUSION_CANCELLATION_DOMAIN: &[u8] =
130 b"coven.store-device-exclusion-cancellation.v1\0";
131const OWNER_RECOVERY_NODE_DOMAIN: &[u8] = b"coven.owner-recovery-node.v1\0";
132const ACK_DOMAIN: &[u8] = b"coven.store-ack.v1\0";
133const CIRCLE_ACK_DOMAIN: &[u8] = b"coven.circle-ack.v1\0";
134const CIRCLE_SNAPSHOT_DOMAIN: &[u8] = b"coven.circle-snapshot-meta.v1\0";
135const SNAPSHOT_DOMAIN: &[u8] = b"coven.snapshot-meta.v1\0";
136const MEMBERSHIP_ROLLUP_DOMAIN: &[u8] = b"coven.store-membership-rollup.v1\0";
137const CANDIDATE_FAMILY_DOMAIN: &[u8] = b"coven.candidate-family.v1\0";
138const STREAM_ACTIVATION_ID_DOMAIN: &[u8] = b"coven.stream-activation-id.v1\0";
139const AUTHOR_STREAM_ID_DOMAIN: &[u8] = b"coven.author-stream-id.v1\0";
140const STORE_PUBLICATION_ENTRY_DOMAIN: &[u8] = b"coven.store-publication-entry.v1\0";
141const STORE_CURRENT_PUBLICATION_DOMAIN: &[u8] = b"coven.store-current-publication.v1\0";
142
143#[cfg(test)]
144#[path = "store_commit/tests.rs"]
145mod tests;