ant_registers/
register.rs

1// Copyright 2024 MaidSafe.net limited.
2//
3// This SAFE Network Software is licensed to you under The General Public License (GPL), version 3.
4// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
5// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
6// KIND, either express or implied. Please review the Licences for the specific language governing
7// permissions and limitations relating to use of the SAFE Network Software.
8
9use crate::{error::Result, Error, Permissions, RegisterAddress, RegisterOp};
10#[cfg(feature = "test-utils")]
11use bls::SecretKey;
12use bls::{PublicKey, Signature};
13use serde::{Deserialize, Serialize};
14use std::collections::BTreeSet;
15use xor_name::XorName;
16
17/// Arbitrary maximum size of a register entry.
18const MAX_REG_ENTRY_SIZE: usize = 1024;
19
20/// Maximum number of entries of a register.
21const MAX_REG_NUM_ENTRIES: u16 = 1024;
22
23/// A Register on the SAFE Network
24#[derive(Clone, Eq, PartialEq, PartialOrd, Hash, Serialize, Deserialize, Debug)]
25pub struct Register {
26    /// contains the info of meta (XorName) and owner (PublicKey)
27    address: RegisterAddress,
28    /// Permissions of the Register
29    /// Depending on the permissions, the owner can allow other users to write to the register
30    /// Everyone can always read the Register because all data is public
31    permissions: Permissions,
32}
33
34/// A Signed Register on the SAFE Network
35/// This cryptographically secure version of the Register is used to make sure that the data cannot be tampered with
36#[derive(Clone, Debug, Serialize, Deserialize, PartialOrd, PartialEq, Eq, Hash)]
37pub struct SignedRegister {
38    /// the base register we had at creation
39    register: Register,
40    /// signature over the above register by the owner
41    signature: Signature,
42    /// operations to apply on this register,
43    /// they contain a signature of the writer
44    ops: BTreeSet<RegisterOp>,
45}
46
47impl SignedRegister {
48    /// Create a new SignedRegister
49    pub fn new(register: Register, signature: Signature, ops: BTreeSet<RegisterOp>) -> Self {
50        Self {
51            register,
52            signature,
53            ops,
54        }
55    }
56
57    /// Return the base register. This is the register before any operations have been applied.
58    pub fn base_register(&self) -> &Register {
59        &self.register
60    }
61
62    /// Verfies a SignedRegister
63    pub fn verify(&self) -> Result<()> {
64        let reg_size = self.ops.len();
65        if reg_size >= MAX_REG_NUM_ENTRIES as usize {
66            return Err(Error::TooManyEntries(reg_size));
67        }
68
69        let bytes = self.register.bytes()?;
70        if !self
71            .register
72            .owner()
73            .verify(&self.signature, bytes.as_slice())
74        {
75            return Err(Error::InvalidSignature);
76        }
77
78        for op in &self.ops {
79            self.register.check_register_op(op)?;
80            let size = op.crdt_op.value.len();
81            if size > MAX_REG_ENTRY_SIZE {
82                return Err(Error::EntryTooBig {
83                    size,
84                    max: MAX_REG_ENTRY_SIZE,
85                });
86            }
87        }
88        Ok(())
89    }
90
91    pub fn verify_with_address(&self, address: RegisterAddress) -> Result<()> {
92        if self.register.address() != &address {
93            return Err(Error::InvalidRegisterAddress {
94                requested: Box::new(address),
95                got: Box::new(*self.address()),
96            });
97        }
98        self.verify()
99    }
100
101    /// Merge two SignedRegisters
102    pub fn merge(&mut self, other: &Self) -> Result<()> {
103        self.register.verify_is_mergeable(&other.register)?;
104        self.ops.extend(other.ops.clone());
105        Ok(())
106    }
107
108    /// Merge two SignedRegisters but verify the incoming content
109    /// Significantly slower than merge, use when you want to trust but verify the `other`
110    pub fn verified_merge(&mut self, other: &Self) -> Result<()> {
111        self.register.verify_is_mergeable(&other.register)?;
112        other.verify()?;
113        self.ops.extend(other.ops.clone());
114        Ok(())
115    }
116
117    /// Return the address.
118    pub fn address(&self) -> &RegisterAddress {
119        self.register.address()
120    }
121
122    /// Return the owner of the data.
123    pub fn owner(&self) -> PublicKey {
124        self.register.owner()
125    }
126
127    /// Check and add an Op to the SignedRegister
128    pub fn add_op(&mut self, op: RegisterOp) -> Result<()> {
129        let reg_size = self.ops.len();
130        if reg_size >= MAX_REG_NUM_ENTRIES as usize {
131            return Err(Error::TooManyEntries(reg_size));
132        }
133
134        let size = op.crdt_op.value.len();
135        if size > MAX_REG_ENTRY_SIZE {
136            return Err(Error::EntryTooBig {
137                size,
138                max: MAX_REG_ENTRY_SIZE,
139            });
140        }
141
142        self.register.check_register_op(&op)?;
143        self.ops.insert(op);
144        Ok(())
145    }
146
147    /// Returns the reference to the ops list
148    pub fn ops(&self) -> &BTreeSet<RegisterOp> {
149        &self.ops
150    }
151
152    /// Used in tests.
153    #[cfg(feature = "test-utils")]
154    pub fn test_new_from_address(address: RegisterAddress, owner: &SecretKey) -> Self {
155        let base_register = Register {
156            address,
157            permissions: Permissions::AnyoneCanWrite,
158        };
159        let bytes = if let Ok(bytes) = base_register.bytes() {
160            bytes
161        } else {
162            panic!("Failed to serialize register {base_register:?}");
163        };
164        let signature = owner.sign(bytes);
165        Self::new(base_register, signature, BTreeSet::new())
166    }
167}
168
169impl Register {
170    /// Create a new Register
171    pub fn new(owner: PublicKey, meta: XorName, mut permissions: Permissions) -> Self {
172        permissions.add_writer(owner);
173        Self {
174            address: RegisterAddress { meta, owner },
175            permissions,
176        }
177    }
178
179    /// Returns a bytes version of the Register used for signing
180    /// Use this API when you want to sign a Register withtout providing a secret key to the Register API
181    pub fn bytes(&self) -> Result<Vec<u8>> {
182        rmp_serde::to_vec(self).map_err(|_| Error::SerialisationFailed)
183    }
184
185    /// Return the address.
186    pub fn address(&self) -> &RegisterAddress {
187        &self.address
188    }
189
190    /// Return the owner of the data.
191    pub fn owner(&self) -> PublicKey {
192        self.address.owner()
193    }
194
195    /// Return the permission.
196    pub fn permissions(&self) -> &Permissions {
197        &self.permissions
198    }
199
200    /// Check if a register op is valid for our current register
201    pub fn check_register_op(&self, op: &RegisterOp) -> Result<()> {
202        if self.permissions.can_anyone_write() {
203            return Ok(()); // anyone can write, so no need to check the signature
204        }
205        self.check_user_permissions(op.source)?;
206        op.verify_signature(&op.source)
207    }
208
209    /// Helper to check user write permissions for the given requester's public key.
210    ///
211    /// Returns:
212    /// `Ok(())` if the user can write to this register
213    /// `Err::AccessDenied` if the user cannot write to this register
214    pub fn check_user_permissions(&self, requester: PublicKey) -> Result<()> {
215        if self.permissions.can_write(&requester) {
216            Ok(())
217        } else {
218            Err(Error::AccessDenied(requester))
219        }
220    }
221
222    // Private helper to check if this Register is mergeable with another
223    fn verify_is_mergeable(&self, other: &Self) -> Result<()> {
224        if self.address() != other.address() || self.permissions != other.permissions {
225            return Err(Error::DifferentBaseRegister);
226        }
227        Ok(())
228    }
229}
230
231#[cfg(test)]
232mod tests {
233    use crate::{RegisterCrdt, RegisterOp};
234
235    use super::*;
236
237    use bls::SecretKey;
238    use rand::{thread_rng, Rng};
239    use std::collections::BTreeSet;
240    use xor_name::XorName;
241
242    #[test]
243    fn register_create() {
244        let meta = xor_name::rand::random();
245        let (authority_sk, register) = &gen_reg_replicas(None, meta, None, 1)[0];
246
247        let authority = authority_sk.public_key();
248        assert_eq!(register.owner(), authority);
249        assert_eq!(register.owner(), authority);
250
251        let address = RegisterAddress::new(meta, authority);
252        assert_eq!(*register.address(), address);
253    }
254
255    #[test]
256    fn register_permissions() -> eyre::Result<()> {
257        let owner_sk = SecretKey::random();
258        let owner = owner_sk.public_key();
259        let user_sk_1 = SecretKey::random();
260        let other_user = user_sk_1.public_key();
261        let user_sk_2 = SecretKey::random();
262
263        let meta: XorName = xor_name::rand::random();
264        let address = RegisterAddress { meta, owner };
265
266        // Create replicas where anyone can write to them, including the owner ofc
267        let mut signed_reg_1 = create_reg_replica_with(
268            meta,
269            Some(owner_sk.clone()),
270            Some(Permissions::new_anyone_can_write()),
271        );
272        // ...owner and any other users can both write to them
273        let op = generate_random_op(address, &owner_sk)?;
274        assert!(signed_reg_1.add_op(op).is_ok());
275        let op = generate_random_op(address, &user_sk_1)?;
276        assert!(signed_reg_1.add_op(op).is_ok());
277        let op = generate_random_op(address, &user_sk_2)?;
278        assert!(signed_reg_1.add_op(op).is_ok());
279
280        // Create replicas allowing both the owner and other user to write to them
281        let mut signed_reg_2 = create_reg_replica_with(
282            meta,
283            Some(owner_sk.clone()),
284            Some(Permissions::new_with([other_user])),
285        );
286        // ...owner and the other user can both write to them, others shall fail
287        let op = generate_random_op(address, &owner_sk)?;
288        assert!(signed_reg_2.add_op(op).is_ok());
289        let op = generate_random_op(address, &user_sk_1)?;
290        assert!(signed_reg_2.add_op(op).is_ok());
291        let op = generate_random_op(address, &user_sk_2)?;
292        assert!(signed_reg_2.add_op(op).is_err());
293
294        // Create replicas with the owner as the only allowed to write
295        let mut signed_reg_3 = create_reg_replica_with(meta, Some(owner_sk.clone()), None);
296        // ...owner can write to them
297        let op = generate_random_op(address, &owner_sk)?;
298        assert!(signed_reg_3.add_op(op).is_ok());
299        // ...whilst other user cannot write to them
300        let op = generate_random_op(address, &user_sk_1)?;
301        let res = signed_reg_3.add_op(op);
302        assert!(
303            matches!(&res, Err(err) if err == &Error::AccessDenied(other_user)),
304            "Unexpected result: {res:?}"
305        );
306
307        // Registers with different permission can not be merged
308        let res1 = signed_reg_1.merge(&signed_reg_2);
309        let res2 = signed_reg_2.merge(&signed_reg_1);
310        assert!(
311            matches!(&res1, Err(err) if err == &Error::DifferentBaseRegister),
312            "Unexpected result: {res1:?}"
313        );
314        assert_eq!(res1, res2);
315
316        Ok(())
317    }
318
319    #[test]
320    fn register_query_public_perms() -> eyre::Result<()> {
321        let meta = xor_name::rand::random();
322
323        // one register will allow write ops to anyone
324        let authority_sk1 = SecretKey::random();
325        let authority_pk1 = authority_sk1.public_key();
326        let owner1 = authority_pk1;
327        let perms1 = Permissions::new_anyone_can_write();
328        let replica1 = create_reg_replica_with(meta, Some(authority_sk1), Some(perms1));
329
330        // the other register will allow write ops to 'owner1' and 'owner2' only
331        let authority_sk2 = SecretKey::random();
332        let authority_pk2 = authority_sk2.public_key();
333        let owner2 = authority_pk2;
334        let perms2 = Permissions::new_with([owner1]);
335        let replica2 = create_reg_replica_with(meta, Some(authority_sk2), Some(perms2));
336
337        // dummy owner
338        let sk_rand = SecretKey::random();
339        let random_user = sk_rand.public_key();
340        let sk_rand2 = SecretKey::random();
341        let random_user2 = sk_rand2.public_key();
342
343        // check register 1 is public
344        assert_eq!(replica1.owner(), authority_pk1);
345        assert_eq!(replica1.register.check_user_permissions(owner1), Ok(()));
346        assert_eq!(replica1.register.check_user_permissions(owner2), Ok(()));
347        assert_eq!(
348            replica1.register.check_user_permissions(random_user),
349            Ok(())
350        );
351        assert_eq!(
352            replica1.register.check_user_permissions(random_user2),
353            Ok(())
354        );
355
356        // check register 2 has only owner1 and owner2 write allowed
357        assert_eq!(replica2.owner(), authority_pk2);
358        assert_eq!(replica2.register.check_user_permissions(owner1), Ok(()));
359        assert_eq!(replica2.register.check_user_permissions(owner2), Ok(()));
360        assert_eq!(
361            replica2.register.check_user_permissions(random_user),
362            Err(Error::AccessDenied(random_user))
363        );
364        assert_eq!(
365            replica2.register.check_user_permissions(random_user2),
366            Err(Error::AccessDenied(random_user2))
367        );
368
369        Ok(())
370    }
371
372    #[test]
373    fn exceeding_max_reg_entries_errors() -> eyre::Result<()> {
374        let meta = xor_name::rand::random();
375
376        // one replica will allow write ops to anyone
377        let authority_sk1 = SecretKey::random();
378        let owner = authority_sk1.public_key();
379        let perms1 = Permissions::new_anyone_can_write();
380        let address = RegisterAddress { meta, owner };
381
382        let mut replica = create_reg_replica_with(meta, Some(authority_sk1.clone()), Some(perms1));
383
384        for _ in 0..MAX_REG_NUM_ENTRIES {
385            let op = generate_random_op(address, &authority_sk1)?;
386            assert!(replica.add_op(op).is_ok());
387        }
388
389        let op = generate_random_op(address, &authority_sk1)?;
390
391        let excess_entry = replica.add_op(op);
392
393        match excess_entry {
394            Err(Error::TooManyEntries(size)) => {
395                assert_eq!(size, 1024);
396                Ok(())
397            }
398            anything_else => {
399                eyre::bail!(
400                    "Expected Excess entries error was not found. Instead: {anything_else:?}"
401                )
402            }
403        }
404    }
405
406    // Helpers for tests
407    fn gen_reg_replicas(
408        authority_sk: Option<SecretKey>,
409        meta: XorName,
410        perms: Option<Permissions>,
411        count: usize,
412    ) -> Vec<(SecretKey, SignedRegister)> {
413        let replicas: Vec<(SecretKey, SignedRegister)> = (0..count)
414            .map(|_| {
415                let authority_sk = authority_sk.clone().unwrap_or_else(SecretKey::random);
416                let authority = authority_sk.public_key();
417                let perms = perms.clone().unwrap_or_default();
418                let register = Register::new(authority, meta, perms);
419
420                let signature = authority_sk.sign(register.bytes().unwrap());
421                let signed_reg = SignedRegister::new(register, signature, Default::default());
422
423                (authority_sk, signed_reg)
424            })
425            .collect();
426
427        assert_eq!(replicas.len(), count);
428        replicas
429    }
430
431    fn create_reg_replica_with(
432        meta: XorName,
433        authority_sk: Option<SecretKey>,
434        perms: Option<Permissions>,
435    ) -> SignedRegister {
436        let replicas = gen_reg_replicas(authority_sk, meta, perms, 1);
437        replicas[0].1.clone()
438    }
439
440    fn random_register_entry() -> Vec<u8> {
441        let random_bytes = thread_rng().gen::<[u8; 32]>();
442        random_bytes.to_vec()
443    }
444
445    fn generate_random_op(address: RegisterAddress, writer_sk: &SecretKey) -> Result<RegisterOp> {
446        let mut crdt_reg = RegisterCrdt::new(address);
447        let item = random_register_entry();
448        let (_hash, addr, crdt_op) = crdt_reg.write(item, &BTreeSet::new())?;
449        Ok(RegisterOp::new(addr, crdt_op, writer_sk))
450    }
451}