sn_data_types/sequence/
mod.rs

1// Copyright 2021 MaidSafe.net limited.
2//
3// This SAFE Network Software is licensed to you under the MIT license <LICENSE-MIT
4// https://opensource.org/licenses/MIT> or the Modified BSD license <LICENSE-BSD
5// https://opensource.org/licenses/BSD-3-Clause>, at your option. This file may not be copied,
6// modified, or distributed except according to those terms. Please review the Licences for the
7// specific language governing permissions and limitations relating to use of the SAFE Network
8// Software.
9
10mod metadata;
11mod seq_crdt;
12
13use crate::{Error, PublicKey, Result};
14pub use metadata::{
15    Action, Address, Entries, Entry, Index, Kind, Perm, Permissions, Policy, PrivatePermissions,
16    PrivatePolicy, PublicPermissions, PublicPolicy, User,
17};
18use seq_crdt::{CrdtOperation, SequenceCrdt};
19use serde::{Deserialize, Serialize};
20use std::collections::BTreeMap;
21use std::{fmt::Debug, hash::Hash};
22use xor_name::XorName;
23
24// Type of data used for the 'Actor' in CRDT vector clocks
25type ActorType = String;
26
27/// Data mutation operation to apply to Sequence.
28pub type DataOp<T> = CrdtOperation<ActorType, T>;
29
30/// Public Sequence.
31pub type PublicSeqData = SequenceCrdt<ActorType, PublicPolicy>;
32/// Private Sequence.
33pub type PrivateSeqData = SequenceCrdt<ActorType, PrivatePolicy>;
34
35/// Object storing a Sequence variant.
36#[derive(Clone, Eq, PartialEq, Hash, Serialize, Deserialize, Debug)]
37enum SeqData {
38    /// Public Sequence Data.
39    Public(PublicSeqData),
40    /// Private Sequence Data.
41    Private(PrivateSeqData),
42}
43
44/// Object storing the Sequence
45#[derive(Clone, Eq, PartialEq, Hash, Serialize, Deserialize, Debug)]
46pub struct Data {
47    authority: PublicKey,
48    data: SeqData,
49}
50
51#[allow(clippy::len_without_is_empty)]
52impl Data {
53    /// Constructs a new Public Sequence Data.
54    /// The 'authority' is assumed to be the PK which the messages were and will be
55    /// signed with, whilst the 'actor' is a unique identifier to be used as the
56    /// clock's Dot in all operations generated by this instance.
57    /// If a policy is not provided, a default policy will be set where
58    /// the 'authority' is the owner along with an empty users permissions set.
59    pub fn new_public(
60        authority: PublicKey,
61        actor: ActorType,
62        name: XorName,
63        tag: u64,
64        policy: Option<PublicPolicy>,
65    ) -> Self {
66        let policy = policy.unwrap_or(PublicPolicy {
67            owner: authority,
68            permissions: BTreeMap::new(),
69        });
70
71        Self {
72            authority,
73            data: SeqData::Public(PublicSeqData::new(
74                actor,
75                Address::Public { name, tag },
76                policy,
77            )),
78        }
79    }
80
81    /// Constructs a new Private Sequence Data.
82    /// The 'authority' is assumed to be the PK which the messages were and will be
83    /// signed with, whilst the 'actor' is a unique identifier to be used as the
84    /// clock's Dot in all operations generated by this instance.
85    /// If a policy is not provided, a default policy will be set where
86    /// the 'authority' is the owner along with an empty users permissions set.
87    pub fn new_private(
88        authority: PublicKey,
89        actor: ActorType,
90        name: XorName,
91        tag: u64,
92        policy: Option<PrivatePolicy>,
93    ) -> Self {
94        let policy = policy.unwrap_or(PrivatePolicy {
95            owner: authority,
96            permissions: BTreeMap::new(),
97        });
98
99        Self {
100            authority,
101            data: SeqData::Private(PrivateSeqData::new(
102                actor,
103                Address::Private { name, tag },
104                policy,
105            )),
106        }
107    }
108
109    /// Returns the address.
110    pub fn address(&self) -> &Address {
111        match &self.data {
112            SeqData::Public(data) => data.address(),
113            SeqData::Private(data) => data.address(),
114        }
115    }
116
117    /// Returns the kind.
118    pub fn kind(&self) -> Kind {
119        self.address().kind()
120    }
121
122    /// Returns the name.
123    pub fn name(&self) -> &XorName {
124        self.address().name()
125    }
126
127    /// Returns the tag.
128    pub fn tag(&self) -> u64 {
129        self.address().tag()
130    }
131
132    /// Returns `true` if public.
133    pub fn is_public(&self) -> bool {
134        self.kind().is_public()
135    }
136
137    /// Returns `true` if private.
138    pub fn is_private(&self) -> bool {
139        self.kind().is_private()
140    }
141
142    /// Returns the length of the sequence, optionally
143    /// verifying read permissions if a pk is provided
144    pub fn len(&self, requester: Option<PublicKey>) -> Result<u64> {
145        self.check_permission(Action::Read, requester)?;
146
147        Ok(match &self.data {
148            SeqData::Public(data) => data.len(),
149            SeqData::Private(data) => data.len(),
150        })
151    }
152
153    /// Returns true if the sequence is empty.
154    pub fn is_empty(&self, requester: Option<PublicKey>) -> Result<bool> {
155        self.check_permission(Action::Read, requester)?;
156
157        Ok(self.len(None)? == 0)
158    }
159
160    /// Gets a list of items which are within the given indices.
161    /// Note the range of items is [start, end), i.e. the end index is not inclusive.
162    pub fn in_range(
163        &self,
164        start: Index,
165        end: Index,
166        requester: Option<PublicKey>,
167    ) -> Result<Option<Entries>> {
168        self.check_permission(Action::Read, requester)?;
169
170        let entries = match &self.data {
171            SeqData::Public(data) => data.in_range(start, end),
172            SeqData::Private(data) => data.in_range(start, end),
173        };
174
175        Ok(entries)
176    }
177
178    /// Returns a value at 'index', if present.
179    pub fn get(&self, index: Index, requester: Option<PublicKey>) -> Result<Option<&Vec<u8>>> {
180        self.check_permission(Action::Read, requester)?;
181
182        Ok(match &self.data {
183            SeqData::Public(data) => data.get(index),
184            SeqData::Private(data) => data.get(index),
185        })
186    }
187
188    /// Returns the last entry, if it's not empty.
189    pub fn last_entry(&self, requester: Option<PublicKey>) -> Result<Option<&Entry>> {
190        self.check_permission(Action::Read, requester)?;
191
192        Ok(match &self.data {
193            SeqData::Public(data) => data.last_entry(),
194            SeqData::Private(data) => data.last_entry(),
195        })
196    }
197
198    /// Generate unsigned crdt op, adding the new entry.
199    pub fn create_unsigned_append_op(&mut self, entry: Entry) -> Result<DataOp<Entry>> {
200        self.check_permission(Action::Append, None)?;
201
202        match &mut self.data {
203            SeqData::Public(data) => data.create_append_op(entry, self.authority),
204            SeqData::Private(data) => data.create_append_op(entry, self.authority),
205        }
206    }
207
208    /// Apply a signed data CRDT operation.
209    pub fn apply_op(&mut self, op: DataOp<Entry>) -> Result<()> {
210        self.check_permission(Action::Append, Some(op.source))?;
211
212        match &mut self.data {
213            SeqData::Public(data) => data.apply_op(op),
214            SeqData::Private(data) => data.apply_op(op),
215        }
216    }
217
218    /// Returns user permissions, if applicable.
219    pub fn permissions(&self, user: User, requester: Option<PublicKey>) -> Result<Permissions> {
220        self.check_permission(Action::Read, requester)?;
221
222        let user_perm = match &self.data {
223            SeqData::Public(data) => data.policy().permissions(user).ok_or(Error::NoSuchEntry)?,
224            SeqData::Private(data) => data.policy().permissions(user).ok_or(Error::NoSuchEntry)?,
225        };
226
227        Ok(user_perm)
228    }
229
230    /// Returns the public policy, if applicable.
231    pub fn public_policy(&self) -> Result<&PublicPolicy> {
232        match &self.data {
233            SeqData::Public(data) => Ok(data.policy()),
234            SeqData::Private(_) => Err(Error::InvalidOperation),
235        }
236    }
237
238    /// Returns the private policy, if applicable.
239    pub fn private_policy(&self, requester: Option<PublicKey>) -> Result<&PrivatePolicy> {
240        self.check_permission(Action::Read, requester)?;
241        match &self.data {
242            SeqData::Private(data) => Ok(data.policy()),
243            SeqData::Public(_) => Err(Error::InvalidOperation),
244        }
245    }
246
247    /// Helper to check permissions for given `action`
248    /// for the given requester's public key.
249    ///
250    /// Returns:
251    /// `Ok(())` if the permissions are valid,
252    /// `Err::AccessDenied` if the action is not allowed.
253    pub fn check_permission(&self, action: Action, requester: Option<PublicKey>) -> Result<()> {
254        let requester = requester.unwrap_or(self.authority);
255        match &self.data {
256            SeqData::Public(data) => data.policy().is_action_allowed(requester, action),
257            SeqData::Private(data) => data.policy().is_action_allowed(requester, action),
258        }
259    }
260
261    /// Returns the owner of the data.
262    pub fn owner(&self) -> PublicKey {
263        match &self.data {
264            SeqData::Public(data) => data.policy().owner,
265            SeqData::Private(data) => data.policy().owner,
266        }
267    }
268
269    /// Returns the PK which the messages are expected to be signed with by this replica.
270    pub fn replica_authority(&self) -> PublicKey {
271        self.authority
272    }
273}
274
275#[cfg(test)]
276mod tests {
277    use crate::{
278        utils, Error, Keypair, Result, Sequence, SequenceAddress, SequenceEntry, SequenceIndex,
279        SequenceKind, SequenceOp, SequencePermissions, SequencePrivatePermissions,
280        SequencePrivatePolicy, SequencePublicPermissions, SequencePublicPolicy, SequenceUser,
281    };
282    use anyhow::anyhow;
283    use proptest::prelude::*;
284    use rand::rngs::OsRng;
285    use std::{collections::BTreeMap, sync::Arc};
286    use xor_name::XorName;
287
288    #[test]
289    fn sequence_create_public() {
290        let sequence_name = XorName::random();
291        let sequence_tag = 43_000;
292        let (_, sequence) = &gen_pub_seq_replicas(None, sequence_name, sequence_tag, None, 1)[0];
293
294        assert_eq!(sequence.kind(), SequenceKind::Public);
295        assert_eq!(*sequence.name(), sequence_name);
296        assert_eq!(sequence.tag(), sequence_tag);
297        assert!(sequence.is_public());
298        assert!(!sequence.is_private());
299
300        let sequence_address =
301            SequenceAddress::from_kind(SequenceKind::Public, sequence_name, sequence_tag);
302        assert_eq!(*sequence.address(), sequence_address);
303    }
304
305    #[test]
306    fn sequence_create_private() {
307        let sequence_name = XorName::random();
308        let sequence_tag = 43_000;
309        let (_, sequence) = &gen_priv_seq_replicas(None, sequence_name, sequence_tag, None, 1)[0];
310
311        assert_eq!(sequence.kind(), SequenceKind::Private);
312        assert_eq!(*sequence.name(), sequence_name);
313        assert_eq!(sequence.tag(), sequence_tag);
314        assert!(!sequence.is_public());
315        assert!(sequence.is_private());
316
317        let sequence_address =
318            SequenceAddress::from_kind(SequenceKind::Private, sequence_name, sequence_tag);
319        assert_eq!(*sequence.address(), sequence_address);
320    }
321
322    #[test]
323    fn sequence_concurrent_append_ops() -> Result<()> {
324        let authority_keypair1 = Keypair::new_ed25519(&mut OsRng);
325        let authority1 = authority_keypair1.public_key();
326        let authority_keypair2 = Keypair::new_ed25519(&mut OsRng);
327        let authority2 = authority_keypair2.public_key();
328        let sequence_name: XorName = rand::random();
329        let sequence_tag = 43_000u64;
330
331        // We'll have 'authority1' as the owner in both replicas and
332        // grant permissions for Append to 'authority2' in both replicas
333        let mut perms = BTreeMap::default();
334        let user_perms = SequencePublicPermissions::new(true);
335        let _ = perms.insert(SequenceUser::Key(authority2), user_perms);
336
337        // Instantiate the same Sequence on two replicas with the two diff authorities
338        let mut replica1 = Sequence::new_public(
339            authority1,
340            authority1.to_string(),
341            sequence_name,
342            sequence_tag,
343            Some(SequencePublicPolicy {
344                owner: authority1,
345                permissions: perms.clone(),
346            }),
347        );
348        let mut replica2 = Sequence::new_public(
349            authority2,
350            authority2.to_string(),
351            sequence_name,
352            sequence_tag,
353            Some(SequencePublicPolicy {
354                owner: authority1,
355                permissions: perms,
356            }),
357        );
358
359        // And let's append an item to replica1 with autority1
360        let item1 = b"item1";
361        let append_op1 = sign_sequence_op(
362            replica1.create_unsigned_append_op(item1.to_vec())?,
363            &authority_keypair1,
364        )?;
365        replica1.apply_op(append_op1.clone())?;
366
367        // Let's assert current state on both replicas
368        assert_eq!(replica1.len(None)?, 1);
369        assert_eq!(replica2.len(None)?, 0);
370
371        // Concurrently append anoother item with authority2 on replica2
372        let item2 = b"item2";
373        let append_op2 = sign_sequence_op(
374            replica2.create_unsigned_append_op(item2.to_vec())?,
375            &authority_keypair2,
376        )?;
377        replica2.apply_op(append_op2.clone())?;
378
379        // Item should be appended on replica2
380        assert_eq!(replica2.len(None)?, 1);
381
382        // Append operations are now broadcasted and applied to both replicas
383        replica1.apply_op(append_op2)?;
384        replica2.apply_op(append_op1)?;
385
386        // Let's assert data convergence on both replicas
387        verify_data_convergence(vec![replica1, replica2], 2)?;
388
389        Ok(())
390    }
391
392    #[test]
393    fn sequence_get_in_range() -> anyhow::Result<()> {
394        let mut replicas = create_public_seq_replicas(1);
395        let (authority_keypair, sequence) = &mut replicas[0];
396
397        let entry1 = b"value0".to_vec();
398        let entry2 = b"value1".to_vec();
399        let entry3 = b"value2".to_vec();
400
401        let op1 = sign_sequence_op(
402            sequence.create_unsigned_append_op(entry1.clone())?,
403            &authority_keypair,
404        )?;
405        sequence.apply_op(op1)?;
406
407        let op2 = sign_sequence_op(
408            sequence.create_unsigned_append_op(entry2.clone())?,
409            &authority_keypair,
410        )?;
411        sequence.apply_op(op2)?;
412
413        let op3 = sign_sequence_op(
414            sequence.create_unsigned_append_op(entry3.clone())?,
415            &authority_keypair,
416        )?;
417        sequence.apply_op(op3)?;
418
419        assert_eq!(sequence.len(None)?, 3);
420
421        let index_0 = SequenceIndex::FromStart(0);
422        let index_1 = SequenceIndex::FromStart(1);
423        let index_2 = SequenceIndex::FromStart(2);
424        let end_index = SequenceIndex::FromEnd(0);
425
426        let first_entry = sequence.in_range(index_0, index_1, None)?;
427        assert_eq!(first_entry, Some(vec![entry1.clone()]));
428
429        let all_entries = sequence.in_range(index_0, end_index, None)?;
430        assert_eq!(
431            all_entries,
432            Some(vec![entry1, entry2.clone(), entry3.clone()])
433        );
434
435        let last_entry = sequence.in_range(index_2, end_index, None)?;
436        assert_eq!(last_entry, Some(vec![entry3]));
437
438        let second_entry = sequence.in_range(index_1, SequenceIndex::FromEnd(1), None)?;
439        assert_eq!(second_entry, Some(vec![entry2]));
440
441        let index_3 = SequenceIndex::FromStart(3);
442        match sequence.in_range(index_3, index_3, None) {
443            Ok(None) => Ok(()),
444            Ok(Some(entries)) => Err(anyhow!(
445                "Unexpectedly fetched entries from Sequence: {:?}",
446                entries
447            )),
448            Err(err) => Err(anyhow!(
449                "Unexpected error thrown when trying to fetch from Sequence with out of bound start index: {:?}",
450                err
451            )),
452        }
453    }
454
455    #[test]
456    fn sequence_query_public_policy() -> anyhow::Result<()> {
457        // one replica will allow append ops to anyone
458        let authority_keypair1 = Keypair::new_ed25519(&mut OsRng);
459        let owner1 = authority_keypair1.public_key();
460        let mut perms1 = BTreeMap::default();
461        let _ = perms1.insert(SequenceUser::Anyone, SequencePublicPermissions::new(true));
462        let replica1 = create_public_seq_replica_with(
463            Some(authority_keypair1),
464            Some(SequencePublicPolicy {
465                owner: owner1,
466                permissions: perms1.clone(),
467            }),
468        );
469
470        // the other replica will allow append ops to 'owner1' and 'authority2' only
471        let authority_keypair2 = Keypair::new_ed25519(&mut OsRng);
472        let authority2 = authority_keypair2.public_key();
473        let mut perms2 = BTreeMap::default();
474        let _ = perms2.insert(
475            SequenceUser::Key(owner1),
476            SequencePublicPermissions::new(true),
477        );
478        let replica2 = create_public_seq_replica_with(
479            Some(authority_keypair2),
480            Some(SequencePublicPolicy {
481                owner: authority2,
482                permissions: perms2.clone(),
483            }),
484        );
485
486        assert_eq!(replica1.owner(), owner1);
487        assert_eq!(replica1.replica_authority(), owner1);
488        assert_eq!(replica1.public_policy()?.permissions, perms1);
489        assert_eq!(
490            SequencePermissions::Public(SequencePublicPermissions::new(true)),
491            replica1.permissions(SequenceUser::Anyone, None)?
492        );
493
494        assert_eq!(replica2.owner(), authority2);
495        assert_eq!(replica2.replica_authority(), authority2);
496        assert_eq!(replica2.public_policy()?.permissions, perms2);
497        assert_eq!(
498            SequencePermissions::Public(SequencePublicPermissions::new(true)),
499            replica2.permissions(SequenceUser::Key(owner1), None)?
500        );
501
502        Ok(())
503    }
504
505    #[test]
506    fn sequence_query_private_policy() -> anyhow::Result<()> {
507        let authority_keypair1 = Keypair::new_ed25519(&mut OsRng);
508        let authority1 = authority_keypair1.public_key();
509        let authority_keypair2 = Keypair::new_ed25519(&mut OsRng);
510        let authority2 = authority_keypair2.public_key();
511
512        let mut perms1 = BTreeMap::default();
513        let user_perms1 =
514            SequencePrivatePermissions::new(/*read*/ true, /*append*/ false);
515        let _ = perms1.insert(authority1, user_perms1);
516
517        let mut perms2 = BTreeMap::default();
518        let user_perms2 = SequencePrivatePermissions::new(/*read*/ true, /*append*/ true);
519        let _ = perms2.insert(authority2, user_perms2);
520        let user_perms2 =
521            SequencePrivatePermissions::new(/*read*/ false, /*append*/ true);
522        let _ = perms2.insert(authority1, user_perms2);
523
524        let replica1 = create_private_seq_replica_with(
525            Some(authority_keypair1),
526            Some(SequencePrivatePolicy {
527                owner: authority1,
528                permissions: perms1.clone(),
529            }),
530        );
531
532        let replica2 = create_private_seq_replica_with(
533            Some(authority_keypair2),
534            Some(SequencePrivatePolicy {
535                owner: authority2,
536                permissions: perms2.clone(),
537            }),
538        );
539
540        assert_eq!(replica1.owner(), authority1);
541        assert_eq!(replica1.replica_authority(), authority1);
542        assert_eq!(
543            replica1.private_policy(Some(authority1))?.permissions,
544            perms1
545        );
546        assert_eq!(
547            SequencePermissions::Private(SequencePrivatePermissions::new(true, false)),
548            replica1.permissions(SequenceUser::Key(authority1), None)?
549        );
550
551        assert_eq!(replica2.owner(), authority2);
552        assert_eq!(replica2.replica_authority(), authority2);
553        assert_eq!(
554            replica2.private_policy(Some(authority2))?.permissions,
555            perms2
556        );
557        assert_eq!(
558            SequencePermissions::Private(SequencePrivatePermissions::new(true, true)),
559            replica2.permissions(SequenceUser::Key(authority2), None)?
560        );
561        assert_eq!(
562            SequencePermissions::Private(SequencePrivatePermissions::new(false, true)),
563            replica2.permissions(SequenceUser::Key(authority1), None)?
564        );
565
566        Ok(())
567    }
568
569    #[test]
570    fn sequence_public_append_fails_when_no_perms_for_authority() -> anyhow::Result<()> {
571        // one replica will allow append ops to anyone
572        let authority_keypair1 = Keypair::new_ed25519(&mut OsRng);
573        let owner1 = authority_keypair1.public_key();
574        let mut perms1 = BTreeMap::default();
575        let _ = perms1.insert(SequenceUser::Anyone, SequencePublicPermissions::new(true));
576        let mut replica1 = create_public_seq_replica_with(
577            Some(authority_keypair1.clone()),
578            Some(SequencePublicPolicy {
579                owner: owner1,
580                permissions: perms1,
581            }),
582        );
583
584        // the other replica will *not* allow append ops to 'owner1'
585        let authority_keypair2 = Keypair::new_ed25519(&mut OsRng);
586        let authority2 = authority_keypair2.public_key();
587        let mut perms2 = BTreeMap::default();
588        let _ = perms2.insert(
589            SequenceUser::Key(owner1),
590            SequencePublicPermissions::new(false),
591        );
592        let mut replica2 = create_public_seq_replica_with(
593            Some(authority_keypair2.clone()),
594            Some(SequencePublicPolicy {
595                owner: authority2,
596                permissions: perms2,
597            }),
598        );
599
600        // let's append to both replicas with one first item
601        let item1 = b"item1";
602        let item2 = b"item2";
603        let append_op1 = sign_sequence_op(
604            replica1.create_unsigned_append_op(item1.to_vec())?,
605            &authority_keypair1,
606        )?;
607        replica1.apply_op(append_op1.clone())?;
608        check_op_not_allowed_failure(replica2.apply_op(append_op1))?;
609
610        let append_op2 = sign_sequence_op(
611            replica2.create_unsigned_append_op(item2.to_vec())?,
612            &authority_keypair2,
613        )?;
614        replica1.apply_op(append_op2.clone())?;
615        replica2.apply_op(append_op2)?;
616
617        assert_eq!(replica1.len(None)?, 2);
618        assert_eq!(replica2.len(None)?, 1);
619
620        Ok(())
621    }
622
623    #[test]
624    fn sequence_private_append_fails_when_no_perms_for_authority() -> anyhow::Result<()> {
625        let authority_keypair1 = Keypair::new_ed25519(&mut OsRng);
626        let authority1 = authority_keypair1.public_key();
627        let authority_keypair2 = Keypair::new_ed25519(&mut OsRng);
628        let authority2 = authority_keypair2.public_key();
629
630        let mut perms1 = BTreeMap::default();
631        let user_perms1 =
632            SequencePrivatePermissions::new(/*read*/ false, /*append*/ true);
633        let _ = perms1.insert(authority2, user_perms1);
634
635        let mut perms2 = BTreeMap::default();
636        let user_perms2 =
637            SequencePrivatePermissions::new(/*read*/ true, /*append*/ false);
638        let _ = perms2.insert(authority1, user_perms2);
639
640        let mut replica1 = create_private_seq_replica_with(
641            Some(authority_keypair1.clone()),
642            Some(SequencePrivatePolicy {
643                owner: authority1,
644                permissions: perms1,
645            }),
646        );
647
648        let mut replica2 = create_private_seq_replica_with(
649            Some(authority_keypair2.clone()),
650            Some(SequencePrivatePolicy {
651                owner: authority2,
652                permissions: perms2,
653            }),
654        );
655
656        // let's try to append to both sequences
657        let item1 = b"item1";
658        let item2 = b"item2";
659        let append_op1 = sign_sequence_op(
660            replica1.create_unsigned_append_op(item1.to_vec())?,
661            &authority_keypair1,
662        )?;
663        replica1.apply_op(append_op1.clone())?;
664        check_op_not_allowed_failure(replica2.apply_op(append_op1))?;
665
666        let append_op2 = sign_sequence_op(
667            replica2.create_unsigned_append_op(item2.to_vec())?,
668            &authority_keypair2,
669        )?;
670        replica1.apply_op(append_op2.clone())?;
671        replica2.apply_op(append_op2)?;
672
673        assert_eq!(replica1.len(None)?, 2);
674        assert_eq!(replica2.len(None)?, 1);
675
676        // Let's do some read permissions check now...
677
678        // let's check authority1 can read from replica1 and replica2
679        let data = replica1.get(SequenceIndex::FromStart(0), Some(authority1))?;
680        let last_entry = replica1.last_entry(Some(authority1))?;
681        let from_range = replica1.in_range(
682            SequenceIndex::FromStart(0),
683            SequenceIndex::FromStart(1),
684            Some(authority1),
685        )?;
686        // since op2 is concurrent to op1, we don't know exactly
687        // the order of items appended by op1 and op2 in replica1,
688        // thus we assert for either case which are both valid
689        if data == Some(&item1.to_vec()) {
690            assert_eq!(last_entry, Some(&item2.to_vec()));
691            assert_eq!(from_range, Some(vec![item1.to_vec()]));
692        } else {
693            assert_eq!(data, Some(&item2.to_vec()));
694            assert_eq!(last_entry, Some(&item1.to_vec()));
695            assert_eq!(from_range, Some(vec![item2.to_vec()]));
696        }
697
698        let data = replica2.get(SequenceIndex::FromStart(0), Some(authority1))?;
699        let last_entry = replica2.last_entry(Some(authority1))?;
700        let from_range = replica2.in_range(
701            SequenceIndex::FromStart(0),
702            SequenceIndex::FromStart(1),
703            Some(authority1),
704        )?;
705        assert_eq!(data, Some(&item2.to_vec()));
706        assert_eq!(last_entry, Some(&item2.to_vec()));
707        assert_eq!(from_range, Some(vec![item2.to_vec()]));
708
709        // authority2 cannot read from replica1
710        check_op_not_allowed_failure(replica1.get(SequenceIndex::FromStart(0), Some(authority2)))?;
711        check_op_not_allowed_failure(replica1.last_entry(Some(authority2)))?;
712        check_op_not_allowed_failure(replica1.in_range(
713            SequenceIndex::FromStart(0),
714            SequenceIndex::FromStart(1),
715            Some(authority2),
716        ))?;
717
718        // but authority2 can read from replica2
719        let data = replica2.get(SequenceIndex::FromStart(0), Some(authority2))?;
720        let last_entry = replica2.last_entry(Some(authority2))?;
721        let from_range = replica2.in_range(
722            SequenceIndex::FromStart(0),
723            SequenceIndex::FromStart(1),
724            Some(authority2),
725        )?;
726        assert_eq!(data, Some(&item2.to_vec()));
727        assert_eq!(last_entry, Some(&item2.to_vec()));
728        assert_eq!(from_range, Some(vec![item2.to_vec()]));
729
730        Ok(())
731    }
732
733    // Helpers for tests
734
735    fn sign_sequence_op(
736        mut op: SequenceOp<SequenceEntry>,
737        keypair: &Keypair,
738    ) -> Result<SequenceOp<SequenceEntry>> {
739        let bytes = utils::serialise(&op.crdt_op)?;
740        let signature = keypair.sign(&bytes);
741        op.signature = Some(signature);
742        Ok(op)
743    }
744
745    fn gen_pub_seq_replicas(
746        authority_keypair: Option<Keypair>,
747        name: XorName,
748        tag: u64,
749        policy: Option<SequencePublicPolicy>,
750        count: usize,
751    ) -> Vec<(Keypair, Sequence)> {
752        let replicas: Vec<(Keypair, Sequence)> = (0..count)
753            .map(|_| {
754                let authority_keypair = authority_keypair
755                    .clone()
756                    .unwrap_or_else(|| Keypair::new_ed25519(&mut OsRng));
757                let authority = authority_keypair.public_key();
758                let sequence = Sequence::new_public(
759                    authority,
760                    authority.to_string(),
761                    name,
762                    tag,
763                    policy.clone(),
764                );
765                (authority_keypair, sequence)
766            })
767            .collect();
768
769        assert_eq!(replicas.len(), count);
770        replicas
771    }
772
773    fn gen_priv_seq_replicas(
774        authority_keypair: Option<Keypair>,
775        name: XorName,
776        tag: u64,
777        policy: Option<SequencePrivatePolicy>,
778        count: usize,
779    ) -> Vec<(Keypair, Sequence)> {
780        let replicas: Vec<(Keypair, Sequence)> = (0..count)
781            .map(|_| {
782                let authority_keypair = authority_keypair
783                    .clone()
784                    .unwrap_or_else(|| Keypair::new_ed25519(&mut OsRng));
785                let authority = authority_keypair.public_key();
786                let sequence = Sequence::new_private(
787                    authority,
788                    authority.to_string(),
789                    name,
790                    tag,
791                    policy.clone(),
792                );
793                (authority_keypair, sequence)
794            })
795            .collect();
796
797        assert_eq!(replicas.len(), count);
798        replicas
799    }
800
801    fn create_public_seq_replicas(count: usize) -> Vec<(Keypair, Sequence)> {
802        let sequence_name = XorName::random();
803        let sequence_tag = 43_000;
804
805        gen_pub_seq_replicas(None, sequence_name, sequence_tag, None, count)
806    }
807
808    fn create_public_seq_replica_with(
809        authority_keypair: Option<Keypair>,
810        policy: Option<SequencePublicPolicy>,
811    ) -> Sequence {
812        let sequence_name = XorName::random();
813        let sequence_tag = 43_000;
814        let replicas =
815            gen_pub_seq_replicas(authority_keypair, sequence_name, sequence_tag, policy, 1);
816        replicas[0].1.clone()
817    }
818
819    fn create_private_seq_replica_with(
820        authority_keypair: Option<Keypair>,
821        policy: Option<SequencePrivatePolicy>,
822    ) -> Sequence {
823        let sequence_name = XorName::random();
824        let sequence_tag = 43_000;
825        let replicas =
826            gen_priv_seq_replicas(authority_keypair, sequence_name, sequence_tag, policy, 1);
827        replicas[0].1.clone()
828    }
829
830    // check it fails due to not having permissions
831    fn check_op_not_allowed_failure<T>(result: Result<T>) -> anyhow::Result<()> {
832        match result {
833            Err(Error::AccessDenied(_)) => Ok(()),
834            Err(err) => Err(anyhow!(
835                "Error returned was the unexpected one for a non-allowed op: {}",
836                err
837            )),
838            Ok(_) => Err(anyhow!(
839                "Data operation succeded unexpectedly, an AccessDenied error was expected"
840                    .to_string(),
841            )),
842        }
843    }
844
845    // verify data convergence on a set of replicas and with the expected length
846    fn verify_data_convergence(replicas: Vec<Sequence>, expected_len: u64) -> Result<()> {
847        // verify replicas have the expected length
848        // also verify replicas failed to get with index beyond reported length
849        let index_beyond = SequenceIndex::FromStart(expected_len);
850        for r in &replicas {
851            assert_eq!(r.len(None)?, expected_len);
852            assert_eq!(r.get(index_beyond, None)?, None);
853        }
854
855        // now verify that the items are the same in all replicas
856        for i in 0..expected_len {
857            let index = SequenceIndex::FromStart(i);
858            let r0_entry = replicas[0].get(index, None)?;
859            for r in &replicas {
860                assert_eq!(r0_entry, r.get(index, None)?);
861            }
862        }
863
864        Ok(())
865    }
866
867    // Generate a vec of Sequence replicas of some length, with corresponding vec of keypairs for signing, and the overall owner of the sequence
868    fn generate_replicas(
869        max_quantity: usize,
870    ) -> impl Strategy<Value = Result<(Vec<Sequence>, Arc<Keypair>)>> {
871        let xorname = XorName::random();
872        let tag = 45_000u64;
873        let owner_keypair = Arc::new(Keypair::new_ed25519(&mut OsRng));
874        let owner = owner_keypair.public_key();
875        (1..max_quantity + 1).prop_map(move |quantity| {
876            let mut replicas = Vec::with_capacity(quantity);
877            for _ in 0..quantity {
878                let actor = Keypair::new_ed25519(&mut OsRng).public_key().to_string();
879                let policy = SequencePublicPolicy {
880                    owner,
881                    permissions: BTreeMap::default(),
882                };
883                let replica = Sequence::new_public(owner, actor, xorname, tag, Some(policy));
884
885                replicas.push(replica);
886            }
887
888            Ok((replicas, owner_keypair.clone()))
889        })
890    }
891
892    // Generate a Sequence entry
893    fn generate_seq_entry() -> impl Strategy<Value = Vec<u8>> {
894        "\\PC*".prop_map(|s| s.into_bytes())
895    }
896
897    // Generate a vec of Sequence entries
898    fn generate_dataset(max_quantity: usize) -> impl Strategy<Value = Vec<Vec<u8>>> {
899        prop::collection::vec(generate_seq_entry(), 1..max_quantity + 1)
900    }
901
902    proptest! {
903        #[test]
904        fn proptest_seq_doesnt_crash_with_random_data(
905            s in generate_seq_entry()
906        ) {
907            // Instantiate the same Sequence on two replicas
908            let sequence_name = XorName::random();
909            let sequence_tag = 45_000u64;
910            let owner_keypair = Keypair::new_ed25519(&mut OsRng);
911            let policy = SequencePublicPolicy {
912                owner: owner_keypair.public_key(),
913                permissions: BTreeMap::default(),
914            };
915
916            let mut replicas = gen_pub_seq_replicas(
917                Some(owner_keypair.clone()),
918                sequence_name,
919                sequence_tag,
920                Some(policy),
921                2);
922            let (_, mut replica1) = replicas.remove(0);
923            let (_, mut replica2) = replicas.remove(0);
924
925            // Append an item on replicas
926            let append_op = sign_sequence_op(replica1.create_unsigned_append_op(s)?, &owner_keypair)?;
927            replica1.apply_op(append_op.clone())?;
928            replica2.apply_op(append_op)?;
929
930            verify_data_convergence(vec![replica1, replica2], 1)?;
931        }
932
933        #[test]
934        fn proptest_seq_converge_with_many_random_data(
935            dataset in generate_dataset(1000)
936        ) {
937            // Instantiate the same Sequence on two replicas
938            let sequence_name = XorName::random();
939            let sequence_tag = 43_001u64;
940            let owner_keypair = Keypair::new_ed25519(&mut OsRng);
941            let policy = SequencePublicPolicy {
942                owner: owner_keypair.public_key(),
943                permissions: BTreeMap::default(),
944            };
945
946            // Instantiate the same Sequence on two replicas
947            let mut replicas = gen_pub_seq_replicas(
948                Some(owner_keypair.clone()),
949                sequence_name,
950                sequence_tag,
951                Some(policy),
952                2);
953            let (_, mut replica1) = replicas.remove(0);
954            let (_, mut replica2) = replicas.remove(0);
955
956            let dataset_length = dataset.len() as u64;
957
958            // insert our data at replicas
959            for data in dataset {
960                // Append an item on replica1
961                let append_op = sign_sequence_op(replica1.create_unsigned_append_op(data)?, &owner_keypair)?;
962                replica1.apply_op(append_op.clone())?;
963                // now apply that op to replica 2
964                replica2.apply_op(append_op)?;
965            }
966
967            verify_data_convergence(vec![replica1, replica2], dataset_length)?;
968
969        }
970
971        #[test]
972        fn proptest_seq_converge_with_many_random_data_across_arbitrary_number_of_replicas(
973            dataset in generate_dataset(500),
974            res in generate_replicas(50)
975        ) {
976            let (mut replicas, owner_keypair) = res?;
977            let dataset_length = dataset.len() as u64;
978
979            // insert our data at replicas
980            for data in dataset {
981                // first generate an op from one replica...
982                let op = sign_sequence_op(replicas[0].create_unsigned_append_op(data)?, &owner_keypair)?;
983
984                // then apply this to all replicas
985                for replica in &mut replicas {
986                    replica.apply_op(op.clone())?;
987                }
988            }
989
990            verify_data_convergence(replicas, dataset_length)?;
991        }
992    }
993}