Created
February 12, 2020 15:21
-
-
Save rumkin/85761dee3b75497dc9106a49628d4447 to your computer and use it in GitHub Desktop.
🚧[WIP] Simple code registry implementation.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.5.0; | |
contract Registry { | |
bytes[] names; | |
mapping(bytes32 => Package) packages; | |
struct Package { | |
bytes name; | |
address owner; | |
uint8[] versions; | |
mapping(uint8 => Major) majors; | |
} | |
struct Major { | |
uint8 latestMinor; // Latest minor | |
mapping(uint8 => Minor) minors; | |
} | |
struct Minor { | |
uint16 latestBuild; // Latest build | |
mapping(uint16 => Build) builds; | |
} | |
struct Build { | |
bytes multihash; | |
bool isPublished; | |
} | |
event Release(bytes32 indexed package, uint8 indexed major, uint8 indexed minor, uint16 build, bool published); | |
function register(bytes memory _name) | |
public | |
payable | |
{ | |
bytes32 name = resolve(_name); | |
require(packages[name].owner == address(0), 'owner_not_exists'); | |
packages[name] = Package(_name, msg.sender, new uint8[](0)); | |
names.push(_name); | |
} | |
function available(bytes memory _name) | |
public | |
view | |
returns(bool) | |
{ | |
return packages[resolve(_name)].owner != address(0); | |
} | |
function publish(bytes32 _package, uint8 _major, uint8 _minor, uint16 _build, bytes memory _multihash) | |
public | |
payable | |
{ | |
Package storage package = packages[_package]; | |
require(package.owner == msg.sender); | |
require(this.hasBuild(_package, _major, _minor, _build) == false); | |
require(_major > 0 || _minor > 0); // No 0.0 version is available | |
require(_multihash.length > 0, 'multihash_length'); | |
package.majors[_major].minors[_minor].builds[_build] = Build(_multihash, true); | |
Major memory major = package.majors[_major]; | |
Minor memory minor = package.majors[_major].minors[_minor]; | |
if (package.versions[package.versions.length - 1] < _major) { | |
package.versions.push(_major); | |
} | |
if (major.latestMinor < _minor) { | |
package.majors[_major].latestMinor = _minor; | |
} | |
if (minor.latestBuild < _build) { | |
package.majors[_major].minors[_minor].latestBuild = _build; | |
} | |
emit Release(_package, _major, _minor, _build, true); | |
} | |
function unpublish(bytes32 _package, uint8 _major, uint8 _minor, uint16 _build) | |
public | |
payable | |
{ | |
Package storage package = packages[_package]; | |
require(msg.sender == package.owner); | |
require(isPublished(_package, _major, _minor, _build)); | |
// TODO Latest versions could not be unpublished and should be replaced! | |
package.majors[_major].minors[_minor].builds[_build].isPublished = false; | |
emit Release(_package, _major, _minor, _build, false); | |
} | |
function getName(bytes32 _name) | |
public | |
view | |
returns(bytes memory) | |
{ | |
return packages[_name].name; | |
} | |
function getBuild(bytes32 _package, uint8 _major, uint8 _minor, uint16 _build) | |
internal | |
view | |
returns(Build memory) | |
{ | |
return packages[_package].majors[_major].minors[_minor].builds[_build]; | |
} | |
function hasBuild(bytes32 _package, uint8 _major, uint8 _minor, uint16 _build) | |
public | |
view | |
returns(bool) | |
{ | |
return getBuild(_package, _major, _minor, _build).multihash.length > 0; | |
} | |
function isPublished(bytes32 _package, uint8 _major, uint8 _minor, uint16 _build) | |
public | |
view | |
returns(bool) | |
{ | |
return getBuild(_package, _major, _minor, _build).isPublished; | |
} | |
function getLatestMajorVersion(bytes32 _package) | |
public | |
view | |
returns(uint8) | |
{ | |
return packages[_package].versions[packages[_package].versions.length - 1]; | |
} | |
function getLatestMinorVersion(bytes32 _package, uint8 _major) | |
public | |
view | |
returns(uint8) | |
{ | |
return packages[_package].majors[_major].latestMinor; | |
} | |
function getLatestBuildVersion(bytes32 _package, uint8 _major, uint8 _minor) | |
public | |
view | |
returns(uint16) | |
{ | |
return packages[_package].majors[_major].minors[_minor].latestBuild; | |
} | |
function getLastestMajor(bytes32 _package) | |
public | |
view | |
returns(bytes memory) | |
{ | |
Package memory package = packages[_package]; | |
require(package.owner != address(0x0)); // Package exists | |
if (package.versions.length == 0) { | |
return ''; | |
} | |
uint8 major = package.versions[package.versions.length - 1]; | |
uint8 minor = packages[_package].majors[major].latestMinor; | |
uint16 build = packages[_package].majors[major].minors[minor].latestBuild; | |
return getBuild(_package, major, minor, build).multihash; | |
} | |
function getLatestMinor(bytes32 _package, uint8 _major) | |
public | |
view | |
returns(bytes memory) | |
{ | |
Package memory package = packages[_package]; | |
if (package.owner == address(0x0)) { | |
return ''; | |
} | |
if (package.versions.length == 0) { | |
return ''; | |
} | |
uint8 minor = packages[_package].majors[_major].latestMinor; | |
uint16 build = packages[_package].majors[_major].minors[minor].latestBuild; | |
return getBuild(_package, _major, minor, build).multihash; | |
} | |
function getLatestBuild(bytes32 _package, uint8 _major, uint8 _minor) | |
public | |
view | |
returns(bytes memory) | |
{ | |
Package memory package = packages[_package]; | |
if (package.owner == address(0x0)) { | |
return ''; | |
} | |
if (package.versions.length == 0) { | |
return ''; | |
} | |
Major memory major = packages[_package].majors[_major]; | |
require(major.latestMinor <= _minor); | |
uint16 build = packages[_package].majors[_major].minors[_minor].latestBuild; | |
return getBuild(_package, _major, _minor, build).multihash; | |
} | |
function resolve(bytes memory _value) | |
public | |
pure | |
returns(bytes32) | |
{ | |
return keccak256(_value); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment