1use std::collections::BTreeMap;
2
3use serde::{Deserialize, Serialize};
4use uuid::Uuid;
5
6use crate::crypto::{PublicKey, Secret, SecretShare, SecretShareError};
7use crate::linked_data::{BlockEncoded, DagCborCodec, Link};
8use crate::version::Version;
9
10use super::principal::{Principal, PrincipalRole};
11
12#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
13pub struct Share {
14 principal: Principal,
15 share: SecretShare,
16}
17
18impl Share {
19 pub fn new(share: SecretShare, public_key: PublicKey) -> Self {
20 Self {
21 principal: Principal {
22 role: PrincipalRole::Owner,
23 identity: public_key,
24 },
25 share,
26 }
27 }
28
29 pub fn principal(&self) -> &Principal {
30 &self.principal
31 }
32
33 pub fn share(&self) -> &SecretShare {
34 &self.share
35 }
36}
37
38pub type Shares = BTreeMap<String, Share>;
39
40#[allow(clippy::doc_overindented_list_items)]
53#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
54pub struct Manifest {
55 id: Uuid,
58 name: String,
62 shares: Shares,
66 entry: Link,
68 pins: Link,
71 previous: Option<Link>,
73 height: u64,
75 version: Version,
77}
78
79impl BlockEncoded<DagCborCodec> for Manifest {}
80
81impl Manifest {
82 pub fn new(
84 id: Uuid,
85 name: String,
86 owner: PublicKey,
87 share: SecretShare,
88 entry: Link,
89 pins: Link,
90 height: u64,
91 ) -> Self {
92 Manifest {
93 id,
94 name,
95 shares: BTreeMap::from([(
96 owner.to_hex(),
97 Share {
98 principal: Principal {
99 role: PrincipalRole::Owner,
100 identity: owner,
101 },
102 share,
103 },
104 )]),
105 entry,
106 pins,
107 previous: None,
108 height,
109 version: Version::default(),
110 }
111 }
112
113 pub fn get_share(&self, public_key: &PublicKey) -> Option<&Share> {
114 self.shares.get(&public_key.to_hex())
115 }
116
117 pub fn add_share(
118 &mut self,
119 public_key: PublicKey,
120 secret: Secret,
121 ) -> Result<(), SecretShareError> {
122 let share = SecretShare::new(&secret, &public_key)?;
123 let bucket_share = Share::new(share, public_key);
124 self.shares.insert(public_key.to_hex(), bucket_share);
125 Ok(())
126 }
127
128 pub fn unset_shares(&mut self) {
129 self.shares.clear();
130 }
131
132 pub fn id(&self) -> &Uuid {
133 &self.id
134 }
135
136 pub fn name(&self) -> &str {
137 &self.name
138 }
139
140 pub fn shares(&self) -> &BTreeMap<String, Share> {
141 &self.shares
142 }
143
144 pub fn version(&self) -> &Version {
145 &self.version
146 }
147
148 pub fn entry(&self) -> &Link {
149 &self.entry
150 }
151
152 pub fn set_entry(&mut self, entry: Link) {
153 self.entry = entry;
154 }
155
156 pub fn pins(&self) -> &Link {
157 &self.pins
158 }
159
160 pub fn set_pins(&mut self, pins_link: Link) {
161 self.pins = pins_link;
162 }
163
164 pub fn set_previous(&mut self, previous: Link) {
165 self.previous = Some(previous);
166 }
167
168 pub fn previous(&self) -> &Option<Link> {
169 &self.previous
170 }
171
172 pub fn height(&self) -> u64 {
173 self.height
174 }
175
176 pub fn set_height(&mut self, height: u64) {
177 self.height = height;
178 }
179}
180
181#[cfg(test)]
182mod tests {
183 use super::*;
184 #[allow(unused_imports)]
185 use crate::crypto::{PublicKey, Secret};
186
187 #[test]
188 fn test_share_serialize() {
189 use ipld_core::codec::Codec;
190 use serde_ipld_dagcbor::codec::DagCborCodec;
191
192 let share = SecretShare::default();
193
194 let encoded = DagCborCodec::encode_to_vec(&share).unwrap();
196 let decoded: SecretShare = DagCborCodec::decode_from_slice(&encoded).unwrap();
197
198 assert_eq!(share, decoded);
199 }
200
201 #[test]
202 fn test_principal_serialize() {
203 use ipld_core::codec::Codec;
204 use serde_ipld_dagcbor::codec::DagCborCodec;
205
206 let public_key = crate::crypto::SecretKey::generate().public();
207 let principal = Principal {
208 role: PrincipalRole::Owner,
209 identity: public_key,
210 };
211
212 let encoded = DagCborCodec::encode_to_vec(&principal).unwrap();
214 let decoded: Principal = DagCborCodec::decode_from_slice(&encoded).unwrap();
215
216 assert_eq!(principal, decoded);
217 }
218}