1use serde::{Deserialize, Serialize};
3pub mod batch;
4
5pub const MAX_STORAGE_BYTES: u64 = 600 * 1_048_576;
7pub const MAX_CHUNKS: u64 = 4096;
8pub const MAX_CANDIDATES: i64 = 1024;
9pub const MAX_REQUEST_BYTES: usize = 1_048_576 + 222;
10pub const STAGING_TTL_SECONDS: i64 = 24 * 60 * 60;
11
12#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
15pub struct Budget {
16 pub bytes: u64,
17 pub chunks: u64,
18}
19
20#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
21pub enum Component {
22 DataCatalog,
23 PrefixCatalog,
24 ImageCatalog,
25 Manifest,
26 State,
27 Image([u8; 32]),
28}
29
30impl Component {
31 pub fn is_catalog(self) -> bool {
32 self.catalog().is_some()
33 }
34
35 pub fn catalog(self) -> Option<usize> {
36 match self {
37 Self::DataCatalog => Some(0),
38 Self::PrefixCatalog => Some(1),
39 Self::ImageCatalog => Some(2),
40 _ => None,
41 }
42 }
43
44 pub fn key(self) -> Vec<u8> {
45 match self {
46 Self::DataCatalog => vec![0],
47 Self::PrefixCatalog => vec![1],
48 Self::ImageCatalog => vec![2],
49 Self::Manifest => vec![3],
50 Self::State => vec![4],
51 Self::Image(id) => std::iter::once(5).chain(id).collect(),
52 }
53 }
54
55 pub fn from_key(key: &[u8]) -> Option<Self> {
57 Some(match key {
58 [0] => Self::DataCatalog,
59 [1] => Self::PrefixCatalog,
60 [2] => Self::ImageCatalog,
61 [3] => Self::Manifest,
62 [4] => Self::State,
63 [5, id @ ..] => Self::Image(id.try_into().ok()?),
64 _ => return None,
65 })
66 }
67}
68
69#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
70pub enum Presence {
71 Missing,
72 Verified,
73}
74
75#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
76pub struct ComponentStatus {
77 pub component: Component,
78 pub chunks: Vec<Presence>,
79}
80
81#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
82pub struct StagingStatus {
83 pub descriptor_commitment: [u8; 32],
84 pub stream_id: [u8; 32],
85 pub expires_at: i64,
87 pub budget: Budget,
88 pub components: Vec<ComponentStatus>,
91}
92
93pub const PATH: &str = "/e2ee/bootstrap/v1";
94pub const REQUEST_LIMIT: usize = crate::base64_bytes::encoded_len(MAX_REQUEST_BYTES) + 4096;
95pub const RESPONSE_LIMIT: usize = 1_048_576;
96
97#[derive(Serialize, Deserialize)]
98#[serde(deny_unknown_fields)]
99pub struct Envelope {
100 pub vault: [u8; 32],
101 pub genesis: [u8; 32],
102 pub operation: Operation,
103}
104
105#[derive(Serialize, Deserialize)]
106#[serde(deny_unknown_fields)]
107pub enum Operation {
108 ClaimSetup {
109 #[serde(with = "crate::base64_bytes")]
110 bytes: Vec<u8>,
111 },
112 ClaimBearer {
113 #[serde(with = "crate::base64_bytes")]
114 bytes: Vec<u8>,
115 },
116 Declare {
117 #[serde(with = "crate::base64_bytes")]
118 descriptor: Vec<u8>,
119 budget: Budget,
120 },
121 Status {
122 bootstrap: [u8; 32],
123 },
124 Ensure {
125 bootstrap: [u8; 32],
126 commitment: [u8; 32],
127 },
128 Cancel {
129 bootstrap: [u8; 32],
130 },
131 Publish {
132 bootstrap: [u8; 32],
133 commitment: [u8; 32],
134 #[serde(with = "crate::base64_bytes")]
135 record: Vec<u8>,
136 },
137}
138
139#[derive(Serialize, Deserialize)]
140#[serde(deny_unknown_fields)]
141pub enum Reply {
142 Claimed {
143 vault: [u8; 32],
144 claim: [u8; 32],
145 genesis: [u8; 32],
146 },
147 Missing,
148 Canceled,
149 Staging(StagingStatus),
150 Stored,
151 Published(#[serde(with = "crate::base64_bytes")] Vec<u8>),
152}