RFC 47 – MutableData

This topic is created as a continuation of a post about features of SDs and MDs in the other forum.

MDs are supposed to replace SDs but the new structure is far from perfect:

  • There are features that were present in SDs but are removed in MDs, like the explicit signature list and the possibility to add the receiver’s signature in this list (to allow proof of receiver acceptance of transfer)

  • There are features that were absent in SDs and are still not present in MDs like the possibility to store the history of transactions on an object.

So, I will throw some ideas about missing features to design the ultimate MD structure and then the community can discuss and improve them. I know this should merit a RFC but I don’t have time to write one.

A preliminary remark: MDs are not that bad because:

  • They keep the sane SDs basic principle: an object is identified by a tag and a name in the global XOR namespace

  • They add the very useful notion of sub-objects within such an object (the values of the MDs).

That said, choices in the implementation (like the separation between the values and the owners’ keys and the absence of signatures) limit the potential use cases for MDs:

Usage of an enum wrapping both the owners’ keys and the values would allow some other use cases.

Use case: current MDs:

First, the enum could be initialized by a variant implementing exactly what is currently defined by Maidsafe (modifications and ownership transfers governed by a set of rules and owners globally applicable to a MD):

enum MutableDataEnum {
    GlobalOwnership {
        data: BTreeMap<Vec<u8>, Value>,
        permissions: BTreeMap<User, PermissionSet>,
        version: u64,
        owner: PublicKey,
    },
    // Other variants …
}

pub struct MutableData {
    /// Network address
    name: XorName,
    /// Type tag
    tag: u64,
    /// Data variant
    data: MutableDataEnum,
}

Use case: defunct SDs + partial transfers:

Then we could add a variant to allow modifications and ownership transfers on each value. The creators of the MD would be the initial owners of all the values. With only one value the use cases would be the same as these of SDs, a compatibility layer could even be implemented overs such MDs to revive defunct SDs. But with several values this variant allows SDs on steroids with partial ownership transfers on a value by value basis.

    PartialOwnership {
        data: BTreeMap<Vec<u8>, PartialData>,
    },

Where PartialData structure is defined by:

pub struct PartialData {
    data: Vec<u8>,
    version: u64,
    owner: PublicKey,
}

No permission set is defined because:

  • the owner of an object can do whatever he/she wants with it: modify it, transfer ownership or delete it

  • no new values can be added (the initial creator of the MD object defines the complete list of values)

Use case: previous use case + divisibility

To work around the impossibility to add a new value of previous use case, we could create a special variant with pairs of 2 integers as keys. It would allow an owner of a sub-object to split it into several parts. The owner could then transfer these parts to different owners. For example, the owner of (10, 29) sub-object could split it into 2 objects (10, 21) and (22, 29) and then transfer (10, 21) to a new owner but keep ownership of (22, 29). Routing crate must be able to read the keys to validate divisions.

    DivisibleOwnership {
        data: BTreeMap<(u64, u64), PartialData>,
    },

Where PartialData structure is the same as above.

Use case: legal applications (for property titles management and audit systems).

Finally, we could add a variant to allow tracing of all modifications and ownership transfers. The aim is to retain the complete history of the object. The keys of sub-objects are the version numbers and routing crate must be able to read them to validate new version. Signatures are added to each value to prove history of ownership. Contrary to other variants where all values could be modified or deleted in parallel, here none can be modified, nor deleted. Values can only be added one by one and each new value is a new version of the whole object with a new data and/or new owners.

    HistoricalOwnership {
        data: BTreeMap<u64, HistoricalData>,
    },

Where HistoricalData structure is defined by:

pub struct HistoricalData {
    data: Vec<u8>,
    owners: BTreeSet<PublicKey>,
    /// Sign data is composed of MD name, MD tag, u64 key of value (version), data and owners
    /// It must be signed by a majority of owners of previous version and
    /// all the new owners (so that no one can add someone else public key)
    /// all the signatures are verified by vaults
    signatures: BTreeMap<PublicKey, Signature>,
}

I didn’t try to find a solution that combines both divisibility and history retention. What I propose here seems an enough step forward compared to current MDs which implement none of them.

2 Likes