safe_nd/sequence/
mod.rs

1// Copyright 2020 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::{CrdtDataOperation, CrdtPolicyOperation, Op, SequenceCrdt};
19use serde::{Deserialize, Serialize};
20use std::{
21    collections::BTreeMap,
22    fmt::{self, Debug, Formatter},
23    hash::Hash,
24};
25use xor_name::XorName;
26// Type of data used for the 'Actor' in CRDT vector clocks
27type ActorType = PublicKey;
28
29/// Data mutation operation to apply to Sequence.
30pub type DataWriteOp<T> = CrdtDataOperation<ActorType, T>;
31
32/// Policy mutation operation to apply to Sequence.
33pub type PolicyWriteOp<T> = CrdtPolicyOperation<ActorType, T>;
34
35/// Public Sequence.
36pub type PublicSeqData = SequenceCrdt<ActorType, PublicPolicy>;
37/// Private Sequence.
38pub type PrivateSeqData = SequenceCrdt<ActorType, PrivatePolicy>;
39
40impl Debug for PublicSeqData {
41    fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
42        write!(formatter, "PubSequence {:?}", self.address().name())
43    }
44}
45
46impl Debug for PrivateSeqData {
47    fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
48        write!(formatter, "PrivSequence {:?}", self.address().name())
49    }
50}
51
52/// Write operation to apply to Sequence.
53/// This is used for all kind of CRDT operations made on the Sequence,
54/// i.e. not only on the data but also on the permissions and owner info.
55#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, PartialOrd, Eq, Hash)]
56pub struct WriteOp<T> {
57    /// Address of a Sequence object on the network.
58    pub address: Address,
59    /// The operation to apply.
60    pub crdt_op: Op<T, ActorType>,
61}
62
63/// Object storing a Sequence variant.
64#[derive(Clone, Eq, PartialEq, PartialOrd, Hash, Serialize, Deserialize, Debug)]
65pub enum Data {
66    /// Public Sequence Data.
67    Public(PublicSeqData),
68    /// Private Sequence Data.
69    Private(PrivateSeqData),
70}
71
72impl Data {
73    /// Constructs a new Public Sequence Data.
74    pub fn new_public(actor: ActorType, name: XorName, tag: u64) -> Self {
75        Self::Public(PublicSeqData::new(actor, Address::Public { name, tag }))
76    }
77
78    /// Constructs a new Private Sequence Data.
79    pub fn new_private(actor: ActorType, name: XorName, tag: u64) -> Self {
80        Self::Private(PrivateSeqData::new(actor, Address::Private { name, tag }))
81    }
82
83    /// Returns the address.
84    pub fn address(&self) -> &Address {
85        match self {
86            Data::Public(data) => data.address(),
87            Data::Private(data) => data.address(),
88        }
89    }
90
91    /// Returns the kind.
92    pub fn kind(&self) -> Kind {
93        self.address().kind()
94    }
95
96    /// Returns the name.
97    pub fn name(&self) -> &XorName {
98        self.address().name()
99    }
100
101    /// Returns the tag.
102    pub fn tag(&self) -> u64 {
103        self.address().tag()
104    }
105
106    /// Returns `true` if public.
107    pub fn is_pub(&self) -> bool {
108        self.kind().is_pub()
109    }
110
111    /// Returns `true` if private.
112    pub fn is_private(&self) -> bool {
113        self.kind().is_private()
114    }
115
116    /// Checks permissions for given `action` for the provided user.
117    ///
118    /// Returns:
119    /// `Ok(())` if the permissions are valid,
120    /// `Err::InvalidOwners` if the last owner is invalid,
121    /// `Err::AccessDenied` if the action is not allowed.
122    pub fn check_permission(&self, action: Action, requester: PublicKey) -> Result<()> {
123        macro_rules! check_perm {
124            ($data: ident, $requester: ident, $action: ident) => {
125                $data
126                    .policy(Index::FromEnd(1))
127                    .ok_or(Error::AccessDenied)?
128                    .is_action_allowed($requester, $action)
129            };
130        }
131
132        match self {
133            Data::Public(data) => check_perm!(data, requester, action),
134            Data::Private(data) => check_perm!(data, requester, action),
135        }
136    }
137
138    /// Returns the length of the sequence.
139    pub fn len(&self) -> u64 {
140        match self {
141            Data::Public(data) => data.len(),
142            Data::Private(data) => data.len(),
143        }
144    }
145
146    /// Returns true if the sequence is empty.
147    pub fn is_empty(&self) -> bool {
148        self.len() == 0
149    }
150
151    /// Returns the version of last Policy.
152    pub fn policy_version(&self) -> u64 {
153        match self {
154            Data::Public(data) => data.policy_index(),
155            Data::Private(data) => data.policy_index(),
156        }
157    }
158
159    /// Gets a list of items which are within the given indices.
160    pub fn in_range(&self, start: Index, end: Index) -> Option<Entries> {
161        match self {
162            Data::Public(data) => data.in_range(start, end),
163            Data::Private(data) => data.in_range(start, end),
164        }
165    }
166
167    /// Returns a value at 'index', if present.
168    pub fn get(&self, index: Index) -> Option<&Vec<u8>> {
169        match self {
170            Data::Public(data) => data.get(index),
171            Data::Private(data) => data.get(index),
172        }
173    }
174
175    /// Returns the last entry, if present.
176    pub fn last_entry(&self) -> Option<&Entry> {
177        match self {
178            Data::Public(data) => data.last_entry(),
179            Data::Private(data) => data.last_entry(),
180        }
181    }
182
183    /// Appends new entry.
184    pub fn append(&mut self, entry: Entry) -> Result<DataWriteOp<Entry>> {
185        match self {
186            Data::Public(data) => data.append(entry),
187            Data::Private(data) => data.append(entry),
188        }
189    }
190
191    /// Apply a data CRDT operation.
192    pub fn apply_data_op(&mut self, op: DataWriteOp<Entry>) -> Result<()> {
193        match self {
194            Data::Public(data) => data.apply_data_op(op),
195            Data::Private(data) => data.apply_data_op(op),
196        }
197    }
198
199    /// Sets the new policy for Public Sequence.
200    pub fn set_pub_policy(
201        &mut self,
202        owner: PublicKey,
203        permissions: BTreeMap<User, PublicPermissions>,
204    ) -> Result<PolicyWriteOp<PublicPolicy>> {
205        match self {
206            Data::Public(data) => data.set_policy(PublicPolicy { owner, permissions }),
207            Data::Private(_) => Err(Error::InvalidOperation),
208        }
209    }
210
211    /// Sets the new policy for Private Sequence.
212    pub fn set_priv_policy(
213        &mut self,
214        owner: PublicKey,
215        permissions: BTreeMap<PublicKey, PrivatePermissions>,
216    ) -> Result<PolicyWriteOp<PrivatePolicy>> {
217        match self {
218            Data::Private(data) => data.set_policy(PrivatePolicy { owner, permissions }),
219            Data::Public(_) => Err(Error::InvalidOperation),
220        }
221    }
222
223    /// Apply Public Policy CRDT operation.
224    pub fn apply_pub_policy_op(&mut self, op: PolicyWriteOp<PublicPolicy>) -> Result<()> {
225        match (self, &op.crdt_op) {
226            (Data::Public(data), Op::Insert { .. }) => data.apply_policy_op(op),
227            _ => Err(Error::InvalidOperation),
228        }
229    }
230
231    /// Apply Private Policy CRDT operation.
232    pub fn apply_priv_policy_op(&mut self, op: PolicyWriteOp<PrivatePolicy>) -> Result<()> {
233        match self {
234            Data::Private(data) => data.apply_policy_op(op),
235            _ => Err(Error::InvalidOperation),
236        }
237    }
238
239    /// Returns user permissions, if applicable.
240    pub fn permissions(&self, user: User, version: impl Into<Index>) -> Result<Permissions> {
241        let user_perm = match self {
242            Data::Public(data) => data
243                .policy(version)
244                .ok_or(Error::NoSuchEntry)?
245                .permissions(user)
246                .ok_or(Error::NoSuchEntry)?,
247            Data::Private(data) => data
248                .policy(version)
249                .ok_or(Error::NoSuchEntry)?
250                .permissions(user)
251                .ok_or(Error::NoSuchEntry)?,
252        };
253
254        Ok(user_perm)
255    }
256
257    /// Returns public policy, if applicable.
258    pub fn pub_policy(&self, version: impl Into<Index>) -> Result<&PublicPolicy> {
259        let perms = match self {
260            Data::Public(data) => data.policy(version),
261            Data::Private(_) => return Err(Error::InvalidOperation),
262        };
263        perms.ok_or(Error::NoSuchEntry)
264    }
265
266    /// Returns private policy, if applicable.
267    pub fn priv_policy(&self, version: impl Into<Index>) -> Result<&PrivatePolicy> {
268        let perms = match self {
269            Data::Private(data) => data.policy(version),
270            Data::Public(_) => return Err(Error::InvalidOperation),
271        };
272        perms.ok_or(Error::NoSuchEntry)
273    }
274}
275
276impl From<PublicSeqData> for Data {
277    fn from(data: PublicSeqData) -> Self {
278        Data::Public(data)
279    }
280}
281
282impl From<PrivateSeqData> for Data {
283    fn from(data: PrivateSeqData) -> Self {
284        Data::Private(data)
285    }
286}
287
288#[cfg(test)]
289mod tests {
290    use crate::{
291        Error, PublicKey, Result, Sequence, SequenceAddress, SequenceIndex, SequenceKind,
292        SequencePermissions, SequencePrivatePermissions, SequencePublicPermissions, SequenceUser,
293    };
294    use std::collections::BTreeMap;
295    use threshold_crypto::SecretKey;
296    use xor_name::XorName;
297
298    #[test]
299    fn sequence_create_public() {
300        let actor = gen_public_key();
301        let sequence_name = XorName::random();
302        let sequence_tag = 43_000;
303        let sequence = Sequence::new_public(actor, sequence_name, sequence_tag);
304        assert_eq!(sequence.kind(), SequenceKind::Public);
305        assert_eq!(*sequence.name(), sequence_name);
306        assert_eq!(sequence.tag(), sequence_tag);
307        assert!(sequence.is_pub());
308        assert!(!sequence.is_private());
309
310        let sequence_address =
311            SequenceAddress::from_kind(SequenceKind::Public, sequence_name, sequence_tag);
312        assert_eq!(*sequence.address(), sequence_address);
313    }
314
315    #[test]
316    fn sequence_create_private() {
317        let actor = gen_public_key();
318        let sequence_name = XorName::random();
319        let sequence_tag = 43_000;
320        let sequence = Sequence::new_private(actor, sequence_name, sequence_tag);
321        assert_eq!(sequence.kind(), SequenceKind::Private);
322        assert_eq!(*sequence.name(), sequence_name);
323        assert_eq!(sequence.tag(), sequence_tag);
324        assert!(!sequence.is_pub());
325        assert!(sequence.is_private());
326
327        let sequence_address =
328            SequenceAddress::from_kind(SequenceKind::Private, sequence_name, sequence_tag);
329        assert_eq!(*sequence.address(), sequence_address);
330    }
331
332    #[test]
333    fn sequence_append_entry_and_apply() -> Result<()> {
334        let actor = gen_public_key();
335        let sequence_name = XorName::random();
336        let sequence_tag = 43_000;
337        let mut replica1 = Sequence::new_public(actor, sequence_name, sequence_tag);
338        let mut replica2 = Sequence::new_public(actor, sequence_name, sequence_tag);
339
340        let mut perms1 = BTreeMap::default();
341        let user_perms1 = SequencePublicPermissions::new(true, false);
342        let _ = perms1.insert(SequenceUser::Anyone, user_perms1);
343        let policy_op = replica1.set_pub_policy(actor, perms1)?;
344        replica2.apply_pub_policy_op(policy_op)?;
345
346        let entry1 = b"value0".to_vec();
347        let entry2 = b"value1".to_vec();
348
349        let op1 = replica1.append(entry1.clone())?;
350        let op2 = replica1.append(entry2.clone())?;
351
352        // we apply the operations in different order, to verify that doesn't affect the result
353        replica2.apply_data_op(op2)?;
354        replica2.apply_data_op(op1)?;
355
356        assert_eq!(replica1.len(), 2);
357        assert_eq!(replica2.len(), 2);
358
359        let index_0 = SequenceIndex::FromStart(0);
360        let first_entry = replica1.get(index_0);
361        assert_eq!(first_entry, Some(&entry1));
362        assert_eq!(first_entry, replica2.get(index_0));
363
364        let index_1 = SequenceIndex::FromStart(1);
365        let second_entry = replica1.get(index_1);
366        assert_eq!(second_entry, Some(&entry2));
367        assert_eq!(second_entry, replica2.get(index_1));
368
369        let last_entry = replica1.last_entry();
370        assert_eq!(last_entry, Some(&entry2));
371        assert_eq!(last_entry, replica2.last_entry());
372
373        Ok(())
374    }
375
376    #[test]
377    fn sequence_public_set_policy_and_apply() -> Result<()> {
378        let actor = gen_public_key();
379        let sequence_name = XorName::random();
380        let sequence_tag = 43_000;
381        let mut replica1 = Sequence::new_public(actor, sequence_name, sequence_tag);
382        let mut replica2 = Sequence::new_public(actor, sequence_name, sequence_tag);
383
384        let mut perms1 = BTreeMap::default();
385        let user_perms1 = SequencePublicPermissions::new(true, false);
386        let _ = perms1.insert(SequenceUser::Anyone, user_perms1);
387
388        let mut perms2 = BTreeMap::default();
389        let user_perms2 = SequencePublicPermissions::new(false, true);
390        let _ = perms2.insert(SequenceUser::Key(actor), user_perms2);
391
392        let op1 = replica1.set_pub_policy(actor, perms1.clone())?;
393        let op2 = replica1.set_pub_policy(actor, perms2.clone())?;
394
395        // if we apply the operations in different order it should fail
396        // as op2 is not causally ready in replica2, it depends on op1
397        check_not_causally_ready_failure(replica2.apply_pub_policy_op(op2.clone()))?;
398
399        // let's apply op1 first then
400        replica2.apply_pub_policy_op(op1)?;
401        replica2.apply_pub_policy_op(op2)?;
402
403        assert_eq!(replica1.policy_version(), 2);
404        assert_eq!(replica2.policy_version(), 2);
405
406        let index_0 = SequenceIndex::FromStart(0);
407        let first_entry = replica1.pub_policy(index_0)?;
408        assert_eq!(first_entry.permissions, perms1);
409        assert_eq!(first_entry.owner, actor);
410        assert_eq!(first_entry, replica2.pub_policy(index_0)?);
411        assert_eq!(
412            SequencePermissions::Pub(user_perms1),
413            replica1.permissions(SequenceUser::Anyone, index_0)?
414        );
415
416        let index_1 = SequenceIndex::FromStart(1);
417        let second_entry = replica1.pub_policy(index_1)?;
418        assert_eq!(second_entry.permissions, perms2);
419        assert_eq!(second_entry.owner, actor);
420        assert_eq!(second_entry, replica2.pub_policy(index_1)?);
421        assert_eq!(
422            SequencePermissions::Pub(user_perms2),
423            replica1.permissions(SequenceUser::Key(actor), index_1)?
424        );
425
426        Ok(())
427    }
428
429    #[test]
430    fn sequence_private_set_policy_and_apply() -> Result<()> {
431        let actor1 = gen_public_key();
432        let actor2 = gen_public_key();
433        let sequence_name = XorName::random();
434        let sequence_tag = 43_000;
435        let mut replica1 = Sequence::new_private(actor1, sequence_name, sequence_tag);
436        let mut replica2 = Sequence::new_private(actor2, sequence_name, sequence_tag);
437
438        let mut perms1 = BTreeMap::default();
439        let user_perms1 = SequencePrivatePermissions::new(true, false, true);
440        let _ = perms1.insert(actor1, user_perms1);
441
442        let mut perms2 = BTreeMap::default();
443        let user_perms2 = SequencePrivatePermissions::new(false, true, false);
444        let _ = perms2.insert(actor2, user_perms2);
445
446        let op1 = replica1.set_priv_policy(actor2, perms1.clone())?;
447        let op2 = replica1.set_priv_policy(actor1, perms2.clone())?;
448
449        // if we apply the operations in different order it should fail
450        // as op2 is not causally ready in replica2, it depends on op1
451        check_not_causally_ready_failure(replica2.apply_priv_policy_op(op2.clone()))?;
452
453        // let's apply op1 first then
454        replica2.apply_priv_policy_op(op1)?;
455        replica2.apply_priv_policy_op(op2)?;
456
457        assert_eq!(replica1.policy_version(), 2);
458        assert_eq!(replica2.policy_version(), 2);
459
460        let index_0 = SequenceIndex::FromStart(0);
461        let first_entry = replica1.priv_policy(index_0)?;
462        assert_eq!(first_entry.permissions, perms1);
463        assert_eq!(first_entry.owner, actor2);
464        assert_eq!(first_entry, replica2.priv_policy(index_0)?);
465        assert_eq!(
466            SequencePermissions::Priv(user_perms1),
467            replica1.permissions(SequenceUser::Key(actor1), index_0)?
468        );
469
470        let index_1 = SequenceIndex::FromStart(1);
471        let second_entry = replica1.priv_policy(index_1)?;
472        assert_eq!(second_entry.permissions, perms2);
473        assert_eq!(second_entry.owner, actor1);
474        assert_eq!(second_entry, replica2.priv_policy(index_1)?);
475        assert_eq!(
476            SequencePermissions::Priv(user_perms2),
477            replica1.permissions(SequenceUser::Key(actor2), index_1)?
478        );
479
480        Ok(())
481    }
482
483    #[test]
484    fn sequence_concurrent_policy_and_data_ops() -> Result<()> {
485        let actor1 = gen_public_key();
486        let actor2 = gen_public_key();
487        let sdata_name: XorName = rand::random();
488        let sdata_tag = 43_000u64;
489
490        // Instantiate the same Sequence on two replicas with two diff actors
491        let mut replica1 = Sequence::new_public(actor1, sdata_name, sdata_tag);
492        let mut replica2 = Sequence::new_public(actor2, sdata_name, sdata_tag);
493
494        // Set Actor1 as the owner in both replicas and
495        // grant authorisation for Append to Actor2 in both replicas
496        let mut perms = BTreeMap::default();
497        let user_perms =
498            SequencePublicPermissions::new(/*append=*/ true, /*admin=*/ false);
499        let _ = perms.insert(SequenceUser::Key(actor2), user_perms);
500        let grant_op = replica1.set_pub_policy(actor1, perms)?;
501        replica2.apply_pub_policy_op(grant_op)?;
502
503        // And let's append both replicas with one first item
504        let item1 = b"item1";
505        let append_op1 = replica1.append(item1.to_vec())?;
506        replica2.apply_data_op(append_op1)?;
507
508        // Let's assert initial state on both replicas
509        assert_eq!(replica1.len(), 1);
510        assert_eq!(replica1.policy_version(), 1);
511        assert_eq!(replica2.len(), 1);
512        assert_eq!(replica2.policy_version(), 1);
513
514        // We revoke authorisation for Actor2 locally on replica1
515        let revoke_op = replica1.set_pub_policy(actor1, BTreeMap::default())?;
516        // New Policy should have been set on replica1
517        assert_eq!(replica1.policy_version(), 2);
518
519        // Concurrently append an item with Actor2 on replica2
520        let item2 = b"item2";
521        let append_op2 = replica2.append(item2.to_vec())?;
522        // Item should be appended on replica2
523        assert_eq!(replica2.len(), 2);
524
525        // Append operation is broadcasted and applied on replica1 using old Policy
526        replica1.apply_data_op(append_op2)?;
527        assert_eq!(replica1.len(), 1);
528
529        // Now revoke operation is broadcasted and applied on replica2
530        replica2.apply_pub_policy_op(revoke_op)?;
531        assert_eq!(replica2.policy_version(), 2);
532        assert_eq!(replica2.len(), 1);
533
534        // Let's assert that append_op2 created a branch of data on both replicas
535        // due to new policy having been applied concurrently, thus only first
536        // item shall be returned from main branch of data
537        verify_data_convergence(&[&replica1, &replica2], 1);
538
539        Ok(())
540    }
541
542    #[test]
543    fn sequence_causality_between_data_and_policy_ops() -> Result<()> {
544        let actor1 = gen_public_key();
545        let actor2 = gen_public_key();
546        let actor3 = gen_public_key();
547        let sdata_name: XorName = rand::random();
548        let sdata_tag = 43_001u64;
549
550        // Instantiate the same Sequence on three replicas with three diff actors
551        let mut replica1 = Sequence::new_public(actor1, sdata_name, sdata_tag);
552        let mut replica2 = Sequence::new_public(actor2, sdata_name, sdata_tag);
553        let mut replica3 = Sequence::new_public(actor3, sdata_name, sdata_tag);
554
555        // Set Actor1 as the owner in all replicas, with empty users permissions yet
556        let owner_op = replica1.set_pub_policy(actor1, BTreeMap::default())?;
557        replica2.apply_pub_policy_op(owner_op.clone())?;
558        replica3.apply_pub_policy_op(owner_op)?;
559
560        // Grant authorisation for Append to Actor3 in replica1 and apply to replica3 too
561        let mut perms = BTreeMap::default();
562        let user_perms =
563            SequencePublicPermissions::new(/*append=*/ true, /*admin=*/ false);
564        let _ = perms.insert(SequenceUser::Key(actor3), user_perms);
565        let grant_op = replica1.set_pub_policy(actor1, perms)?;
566        replica3.apply_pub_policy_op(grant_op.clone())?;
567
568        // Let's assert the state on three replicas
569        assert_eq!(replica1.len(), 0);
570        assert_eq!(replica1.policy_version(), 2);
571        assert_eq!(replica2.len(), 0);
572        assert_eq!(replica2.policy_version(), 1);
573        assert_eq!(replica3.len(), 0);
574        assert_eq!(replica3.policy_version(), 2);
575
576        // We append an item with Actor3 on replica3
577        let item = b"item0";
578        let append_op = replica3.append(item.to_vec())?;
579        assert_eq!(replica3.len(), 1);
580
581        // Append op is broadcasted and applied on replica1
582        replica1.apply_data_op(append_op.clone())?;
583        assert_eq!(replica1.len(), 1);
584
585        // And now append op is broadcasted and applied on replica2
586        // It should be rejected on replica2 as it's not causally ready
587        check_not_causally_ready_failure(replica2.apply_data_op(append_op.clone()))?;
588        assert_eq!(replica2.len(), 0);
589
590        // So let's apply grant operation to replica2
591        replica2.apply_pub_policy_op(grant_op)?;
592        assert_eq!(replica2.policy_version(), 2);
593
594        // Retrying to apply append op to replica2 should be successful, due
595        // to now being causally ready with the new policy
596        replica2.apply_data_op(append_op)?;
597        verify_data_convergence(&[&replica1, &replica2, &replica3], 1);
598
599        Ok(())
600    }
601
602    #[test]
603    fn sequence_concurrent_policy_ops() -> Result<()> {
604        let actor1 = gen_public_key();
605        let actor2 = gen_public_key();
606        let sdata_name: XorName = rand::random();
607        let sdata_tag = 43_001u64;
608
609        // Instantiate the same Sequence on two replicas with two diff actors
610        let mut replica1 = Sequence::new_public(actor1, sdata_name, sdata_tag);
611        let mut replica2 = Sequence::new_public(actor2, sdata_name, sdata_tag);
612
613        // Set Actor1 as the owner and Actor2 with append perms in all replicas
614        let mut perms = BTreeMap::default();
615        let user_perms =
616            SequencePublicPermissions::new(/*append=*/ true, /*admin=*/ false);
617        let _ = perms.insert(SequenceUser::Key(actor2), user_perms);
618        let owner_op = replica1.set_pub_policy(actor1, perms.clone())?;
619        replica2.apply_pub_policy_op(owner_op)?;
620
621        // Append item on replica1, and apply it to replica2
622        let item0 = b"item0".to_vec();
623        let append_op = replica1.append(item0)?;
624        replica2.apply_data_op(append_op)?;
625
626        // Let's assert the state on both replicas
627        assert_eq!(replica1.len(), 1);
628        assert_eq!(replica1.policy_version(), 1);
629        assert_eq!(replica2.len(), 1);
630        assert_eq!(replica2.policy_version(), 1);
631
632        // Concurrently set new policy (new owner) on both replicas
633        let owner_op_1 = replica1.set_pub_policy(actor2, perms.clone())?;
634        let owner_op_2 = replica2.set_pub_policy(actor2, perms)?;
635        // ...and concurrently append a new item on top of their own respective new policies
636        let item1_r1 = b"item1_replica1".to_vec();
637        let item1_r2 = b"item1_replica2".to_vec();
638        let append_op1 = replica1.append(item1_r1)?;
639        let append_op2 = replica2.append(item1_r2)?;
640
641        assert_eq!(replica1.len(), 2);
642        assert_eq!(replica2.len(), 2);
643
644        // Let's now apply policy the other replica
645        replica1.apply_pub_policy_op(owner_op_2)?;
646        replica2.apply_pub_policy_op(owner_op_1)?;
647
648        assert_eq!(replica1.policy_version(), 3);
649        assert_eq!(replica2.policy_version(), 3);
650
651        // Let's now apply the append ops on the other replica
652        replica1.apply_data_op(append_op2)?;
653        replica2.apply_data_op(append_op1)?;
654
655        // Let's assert the state on all replicas to assure convergence
656        // One of the items appended concurrently should not belong to
657        // the master branch of the data thus we should see only 2 items
658        verify_data_convergence(&[&replica1, &replica2], 2);
659
660        Ok(())
661    }
662
663    #[test]
664    fn sequence_old_data_op() -> Result<()> {
665        let actor1 = gen_public_key();
666        let actor2 = gen_public_key();
667        let sdata_name: XorName = rand::random();
668        let sdata_tag = 43_001u64;
669
670        // Instantiate the same Sequence on two replicas with two diff actors
671        let mut replica1 = Sequence::new_public(actor1, sdata_name, sdata_tag);
672        let mut replica2 = Sequence::new_public(actor2, sdata_name, sdata_tag);
673
674        // Set Actor1 as the owner and Actor2 with append perms in all replicas
675        let mut perms = BTreeMap::default();
676        let user_perms =
677            SequencePublicPermissions::new(/*append=*/ true, /*admin=*/ false);
678        let _ = perms.insert(SequenceUser::Key(actor2), user_perms);
679        let owner_op = replica1.set_pub_policy(actor1, perms)?;
680        replica2.apply_pub_policy_op(owner_op)?;
681
682        // Append an item on replica1
683        let item0 = b"item0".to_vec();
684        let append_op = replica1.append(item0)?;
685
686        // A new Policy is set in replica1 and applied to replica2
687        let policy_op = replica1.set_pub_policy(actor1, BTreeMap::default())?;
688        replica2.apply_pub_policy_op(policy_op)?;
689
690        // Now the old append op is applied to replica2
691        replica2.apply_data_op(append_op)?;
692
693        assert_eq!(replica1.policy_version(), 2);
694        assert_eq!(replica2.policy_version(), 2);
695
696        verify_data_convergence(&[&replica1, &replica2], 1);
697
698        Ok(())
699    }
700
701    // Helpers for tests
702
703    fn gen_public_key() -> PublicKey {
704        PublicKey::Bls(SecretKey::random().public_key())
705    }
706
707    // check it fails due to not being causally ready
708    fn check_not_causally_ready_failure(result: Result<()>) -> Result<()> {
709        match result {
710            Err(Error::OpNotCausallyReady) => Ok(()),
711            Err(err) => Err(Error::Unexpected(format!(
712                "Error returned was the unexpected one: {}",
713                err
714            ))),
715            Ok(()) => Err(Error::Unexpected(
716                "Data op applied unexpectedly".to_string(),
717            )),
718        }
719    }
720
721    // verify data convergence on a set of replicas and with the expected length
722    fn verify_data_convergence(replicas: &[&Sequence], expected_len: u64) {
723        // verify replicas have the expected length
724        // also verify replicas failed to get with index beyond reported length
725        let index_beyond = SequenceIndex::FromStart(expected_len);
726        for r in replicas {
727            assert_eq!(r.len(), expected_len);
728            assert_eq!(r.get(index_beyond), None);
729        }
730
731        // now verify that the items are the same in all replicas
732        for i in 0..expected_len {
733            let index = SequenceIndex::FromStart(i);
734            let r0_entry = replicas[0].get(index);
735            for r in replicas {
736                assert_eq!(r0_entry, r.get(index));
737            }
738        }
739    }
740}