Skip to content

Instantly share code, notes, and snippets.

@rumkin
Created February 12, 2020 15:21
Show Gist options
  • Save rumkin/85761dee3b75497dc9106a49628d4447 to your computer and use it in GitHub Desktop.
Save rumkin/85761dee3b75497dc9106a49628d4447 to your computer and use it in GitHub Desktop.
🚧[WIP] Simple code registry implementation.
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