Client: Aragon Versioning Protocol

Created on 27 Jun 2017  ·  11Comments  ·  Source: aragon/client

Goals:

  • Fetch a code packages
  • Automatically update code packages with new versions
  • Know that you have the developer-published version of the package
  • Isolate the modules from the rest of the modules/the application

Requires:

  • Decentralized storage system: IPFS/Swarm
  • Trustless identity system: Ethereum accounts
  • Trustless timestamping system: Ethereum
  • Sandbox to execute JS

Proposed flow for releasing a new version of a codebase:

What would be included in a transaction to the _Metadata repository_ would be:

  • URI where that code package could be found
  • Hash of that code package

Since the hash of the payload is embedded on the Ethereum transaction, we don’t care about who owns the IPFS keypair, for example. Maximum security can be enforced at _Dev_, for example making _Dev_ a multisig. That way, you can enforce however much security do you want by writing or using a contract. It also helps abstract the underlying storage system. This could work with any kind of storage, but of course decentralized storage protocols are preferred.

App would be listening for events in multiple repos and fetch new code packages accordingly.

This base protocol would be pretty generic and agnostic. But knowing that, in our case, we will primarily work on with JavaScript and web tech, we could go a step further and implement a full replacement for NPM.

This would be as simple as having a package.json manifest in all packages, where you can declare a package’s dependencies, and then fetching those dependencies. You could either state them with the Ethereum address of the _Metadata repository_ where it lives, or… you could use ENS! We could own something like aragoncodebases.eth and give out developers subdomains for their _Metadata repositories_. Then you could just point to that subdomain as a dependency.

Asks:

  • @harshjv to look into the sandboxing part, but I think it's safe to assume that it will have no impact on this protocol
  • We need a better name 📦
  • Thoughts? Ideas?
enhancement

Most helpful comment

It took me a bit to get it aswell @onbjerg.

The idea is to have a fully abstracted versioning protocol on top of ETH that keeps track of different
versions of blobs of data that can be located elsewhere (IPFS, Swarm, or even the ETH chain). It provides a common interface for updating the versions and a way to look them up (ENS resolver).

Then we can build the Aragon Package Manager, that implements AVP and its blobs of data are Aragon packages that can be stored anywhere.

All 11 comments

Implementation proposal:

  • We will deploy a RepoFactory
  • Anyone will be able to call RepoFactory to deploy a new Repo, with the sender being the owner (which we will call Dev)
  • Dev, which could be an account, a multisig or any other contract, will be able to push new versions to Repo
  • Versions will have the following data: URI where the code package can be found, hash of the code package, and a numeric version
  • We should implement a resolver, so RepoAddr@PackageVersion fetches the given version of that package
  • Later on, we could implement an ENS resolves so RepoName@PackageVersion also resolves

What do you think @izqui @harshjv?

Good idea, i like the word 'Package' more than 'Repo' for this concept, as modules can be thought of a package of contracts and frontend code.

Did a quick Solidity spike to think a bit about the data structures. Basically a version of a package could have a factory address for deploying an instance of the contract for that particular version and the IPFS hash for the frontend.

The ENS thing is totally doable I'd imagine something like: latest.ownership.[domain].eth or 170.bylaws.[domain].eth

contract Package is Ownable {
    struct Version {
        uint32 semanticVersion; 
        address contractApplicationFactory;
        bytes32 frontendIPFSHash; // is it bytes32?
    }

    mapping (uint32 => uint256) public versionIdBySemanticVersion;
    uint32 public lastVersion;
    Version[] versions;

    function addVersion(uint32 _semanticVersion, address _contract, bytes32 _ipfs) onlyOwner {
        uint versionId = versions.push(Version(_semanticVersion, _contract, _ipfs)) - 1;
        versionIdBySemanticVersion[_semanticVersion] = _semanticVersion;
        lastVersion = _semanticVersion;
    }
}

That's it! Regarding ENS, makes a lot of sense. I honestly don't have strong feelings of Package vs Repo, seems like a Repo contains different Packages (could be versions or other packages), but on the other hand a single Package contains different versions. So yeah, Package makes sense.

BTW @harshjv look at @izqui's snippet above, maybe it is of inspiration

@izqui Yep, bytes32 for ipfs mutihash.

Since we are dealing with prebuilt packages, can we expect the contract address in some json file? In our case, a module.json having contractAddress field. That will make a generic Package repo. What do you think?

Yes, talked to Luis about that.

Will follow up with an updated proposal next week :)

El vie., 7 jul. 2017 a las 13:07, Harsh Vakharia (notifications@github.com)
escribió:

@izqui https://github.com/izqui Yep, bytes32 for ipfs mutihash.

Since we are dealing with prebuilt packages, can we expect the contract
address in some json file? In our case, a module.json having
contractAddress field.


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/aragon/aragon/issues/19#issuecomment-313653250, or mute
the thread
https://github.com/notifications/unsubscribe-auth/AAbTYJcH9AdUjEehVSjifcHNnX57nvlmks5sLhF9gaJpZM4OG6YP
.

By the way, wouldn't Aragon Packaging Protocol or Aragon Package Protocol make more sense, since we're packaging modules? Also the abbreviation would be APP 😁

@onbjerg the thing is that this is very much abstracted away from modules, it is just an agnostic way to version data

It took me a bit to get it aswell @onbjerg.

The idea is to have a fully abstracted versioning protocol on top of ETH that keeps track of different
versions of blobs of data that can be located elsewhere (IPFS, Swarm, or even the ETH chain). It provides a common interface for updating the versions and a way to look them up (ENS resolver).

Then we can build the Aragon Package Manager, that implements AVP and its blobs of data are Aragon packages that can be stored anywhere.

Oh, that makes sense, thanks for clarifying @luisivan and @izqui! I don't think we can find a better name than we have now, then 🙂

Did a bit of work on the AVP and got it to the point where it is working with the ENS.

URI scheme: patch.minor.major.name.aragonpm.eth (aragonpm.eth is currently in reveal face, and chances are we will win the name)

Version syntax can look like it is in counter-intuitive order, but ENS uris work this way, from right to left from more broad to more specific.

The versioning resolver implements the logic that allows to fetch the latest version just checking name.aragonpm.eth or the latest version of a specific major or minor 2.ownership.aragonpm.eth will return the latest version of the 2.x.y release, same with 1.2.ownership.aragonpm.eth will return the latest 2.1.y release.

Only subsequent versions can be added. For example 2.1.1 can turn to 2.1.2, 2.2.0 or 3.0.0, every other version transition is disallowed (enforced by the smart contract).

There was significant discussion about how to make the content(bytes node) part of the ENS standard. For the first version it wasn't included given lack of clarity. Problem is bytes32 is not enough for some hash types (including sha256, as referenced in the ERC discussion). IPFS hashes can be base58 decoded, and a bytes32 could be stored, but then there wouldn't be nowhere to save the hash version.

My proposal (and what it is currently implemented) is the following function signature for resolvers returning data:

function content(bytes32 node) constant returns (uint16 locationId, bytes contentHash);

  • locationId identifies where the content can be found (1 = swarm, 2 = ipfs, 3 = storj...)

    • contentHash is an arbitrary length bytes array that describes how the content can be fetched in the location. It is less efficient than storing fixed sized arrays, but this is way more flexible for future storage locations.

Current implementation: https://github.com/aragon/aragon-package-manager/blob/master/contracts/VersioningProtocol.sol#L45

(repo is private for now, only for org members, code is too early)

Was this page helpful?
0 / 5 - 0 ratings