diff --git a/contracts/src/GitHubAPIReg.sol b/contracts/src/GitHubAPIReg.sol new file mode 100644 index 0000000..71966e8 --- /dev/null +++ b/contracts/src/GitHubAPIReg.sol @@ -0,0 +1,87 @@ +//Author: Ricardo Guilherme Schmidt <3esmit@gmail.com> +pragma solidity ^0.4.11; + +import "lib/ethereans/management/Owned.sol"; + +contract GitHubAPIReg is Owned, usingOraclize { + string credentials = ""; + + event OracleEvent(bytes32 myid, string result, bytes proof); + + function GitHubAPI(){ + oraclize_setProof(proofType_TLSNotary | proofStorage_IPFS); + } + + //owner management + function setAPICredentials(string _client_id, string _client_secret) only_owner { + credentials = strConcat("?client_id=",_client_id,"&client_secret=",_client_secret,""); + } + + function clearAPICredentials() only_owner { + credentials = ""; + } + + function getNextString(bytes _str, uint8 _pos) internal constant returns (string,uint8) { + uint8 start = 0; + uint8 end = 0; + uint strl =_str.length; + for (;strl > _pos; _pos++) { + if (_str[_pos] == '"'){ //Found quotation mark + if(_str[_pos-1] != '\\'){ //is not escaped + end = start == 0 ? 0: _pos; + start = start == 0 ? (_pos+1) : start; + if(end > 0) break; + } + } + } + bytes memory str = new bytes(end-start); + for(_pos=0; _pos _pos; _pos++) { + byte bp = _str[_pos]; + if (bp == ','){ //Find ends + _pos++; break; + }else if ((bp >= 48)&&(bp <= 57)){ //only ASCII numbers + val *= 10; + val += uint(bp) - 48; + } + } + return (val,_pos); + } + + function getNextAddr(bytes _str, uint8 _pos) internal constant returns (address, uint8){ + uint160 iaddr = 0; + uint strl =_str.length; + for(;strl > _pos; _pos++){ + byte bp = _str[_pos]; + if (bp == '0'){ + if (_str[_pos+1] == 'x'){ + for (_pos=_pos+2; _pos<2+2*20; _pos+=2){ + iaddr *= 256; + iaddr += (uint160(hexVal(uint160(_str[_pos])))*16+uint160(hexVal(uint160(_str[_pos+1])))); + } + _pos++; + break; + } + }else if (bp == ','){ + _pos++; + break; + } + } + return (address(iaddr),_pos); + } + + function hexVal(uint val) internal constant returns (uint){ + return val - (val < 58 ? 48 : (val < 97 ? 55 : 87)); + } + +} \ No newline at end of file diff --git a/contracts/src/GitHubAPI.sol b/contracts/src/GitHubOracle.sol similarity index 68% rename from contracts/src/GitHubAPI.sol rename to contracts/src/GitHubOracle.sol index 4049bc1..c8fec8e 100644 --- a/contracts/src/GitHubAPI.sol +++ b/contracts/src/GitHubOracle.sol @@ -7,14 +7,11 @@ import "lib/ethereans/management/Owned.sol"; contract GitHubAPI{ - function register(address _sender, string _github_user, string _gistid) payable; function updateCommits(string _full_name, string _branch, bytes20 _commitid) payable; - function addRepository(string _full_name) payable; function updateIssue(string _full_name, string _issue) payable; } contract DGitI { - function __register(address addrLoaded, uint256 userId, string login); function __addRepository(uint256 projectId, string full_name, string default_branch); function __setHead(uint256 projectId, string branch, bytes20 head); function __setTail(uint256 projectId, string branch, bytes20 tail); @@ -23,49 +20,29 @@ contract DGitI { function __setIssuePoints(uint256 projectId, uint256 issueId, uint256 userId, uint256 points); } -contract GitHubAPIOraclize is GitHubAPI, Owned, usingOraclize{ +contract GitHubOracle is GitHubAPI, Owned, usingOraclize{ using StringLib for string; DGitI dGit - string private cred = "f94095ba1d48038d4a81,36ae0e8b1bc5ad261c936e8f7f730f6c827c221f"; - string private credentials = "?client_id=f94095ba1d48038d4a81&client_secret=36ae0e8b1bc5ad261c936e8f7f730f6c827c221f"; - string private script = "QmU6pSQMDSg8do9eZLAfjzZYcC9JpsMZeB4ZoteGkSe94y"; + string private cred = ""; + string private script = ""; - enum OracleType { ADD_REPOSITORY, SET_USER, CLAIM_COMMIT, CLAIM_CONTINUE, UPDATE_ISSUE } + enum OracleType { CLAIM_COMMIT, CLAIM_CONTINUE, UPDATE_ISSUE } mapping (bytes32 => OracleType) claimType; //temporary db enumerating oraclize calls mapping (bytes32 => CommitClaim) commitClaim; //temporary db for oraclize commit token claim calls - mapping (bytes32 => UserClaim) userClaim; //temporary db for oraclize user register queries - //stores temporary data for oraclize user register request - struct UserClaim { - address sender; - string githubid; - } //stores temporary data for oraclize repository commit claim struct CommitClaim { string repository; bytes20 commitid; } - function GitHubAPIOraclize(){ + function GitHubOracle(string _script){ + script = _script; dGit = DGitI(msg.sender); oraclize_setProof(proofType_TLSNotary | proofStorage_IPFS); } - //register or change a github user ethereum address. 100000000000000000 - function register(address _sender, string _github_user, string _gistid) - payable only_owner{ - bytes32 ocid = oraclize_query("nested", StringLib.concat("[identity] ${[URL] https://gist.githubusercontent.com/",_github_user,"/",_gistid,"/raw/}, ${[URL] json(https://api.github.com/gists/").concat(_gistid,credentials,").owner.[id,login]}")); - claimType[ocid] = OracleType.SET_USER; - userClaim[ocid] = UserClaim({sender: _sender, githubid: _github_user}); - } - - function addRepository(string _repository) - payable only_owner{ - bytes32 ocid = oraclize_query("URL", StringLib.concat("json(https://api.github.com/repos/",_repository,credentials,").$.id,full_name,default_branch"),4000000); - claimType[ocid] = OracleType.ADD_REPOSITORY; - } - function updateCommits(string _repository, string _branch, bytes20 _commitid) payable only_owner{ bytes32 ocid = oraclize_query("computation", [script, "update-new",_repository.concat(",", _branch,",",toString(_commitid)),cred]); @@ -86,13 +63,9 @@ contract GitHubAPIOraclize is GitHubAPI, Owned, usingOraclize{ event OracleEvent(bytes32 myid, string result, bytes proof); //oraclize response callback function __callback(bytes32 myid, string result, bytes proof) { - OracleEvent(myid,result,proof); + OracleEvent(myid, result, proof); if (msg.sender != oraclize.cbAddress()){ throw; - }else if(claimType[myid]==OracleType.SET_USER){ - _register(myid, result); - }else if(claimType[myid] == OracleType.ADD_REPOSITORY){ - _addRepository(myid, result); }else if(claimType[myid]==OracleType.CLAIM_COMMIT){ _updateCommits(myid, result, false); }else if(claimType[myid]==OracleType.CLAIM_CONTINUE){ @@ -103,24 +76,7 @@ contract GitHubAPIOraclize is GitHubAPI, Owned, usingOraclize{ delete claimType[myid]; //should always be deleted } - function _register(bytes32 myid, string result) - internal { - uint256 userId; string memory login; address addrLoaded; - uint8 utype; //TODO - bytes memory v = bytes(result); - uint8 pos = 0; - (addrLoaded,pos) = JSONLib.getNextAddr(v,pos); - (userId,pos) = JSONLib.getNextUInt(v,pos); - (login,pos) = JSONLib.getNextString(v,pos); - if(userClaim[myid].sender == addrLoaded){ - dGit.__register(addrLoaded, userId, login); - } - delete userClaim[myid]; //should always be deleted - } - - - function _addRepository(bytes32 myid, string result) internal //[85743750, "ethereans/TheEtherian", "master"] - { + function _addRepository(bytes32 myid, string result) internal {//[85743750, "ethereans/TheEtherian", "master"] bytes memory v = bytes(result); uint8 pos = 0; string memory temp; @@ -133,8 +89,7 @@ contract GitHubAPIOraclize is GitHubAPI, Owned, usingOraclize{ dGit.__addRepository(projectId,full_name,default_branch); } - function _updateCommits(bytes32 myid, string result, bool continuing) - internal { + function _updateCommits(bytes32 myid, string result, bool continuing) internal { bytes memory v = bytes(result); uint8 pos = 0; string memory temp; @@ -168,8 +123,7 @@ contract GitHubAPIOraclize is GitHubAPI, Owned, usingOraclize{ } } - function _updateIssue(bytes32 myid, string result) - internal { + function _updateIssue(bytes32 myid, string result) internal { bytes memory v = bytes(result); uint8 pos = 0; string memory temp; @@ -195,20 +149,16 @@ contract GitHubAPIOraclize is GitHubAPI, Owned, usingOraclize{ } //owner management - function setAPICredentials(string _client_id, string _client_secret) - only_owner { + function setAPICredentials(string _client_id, string _client_secret) only_owner { cred = StringLib.concat(_client_id,",", _client_secret); - credentials = StringLib.concat("?client_id=",_client_id,"&client_secret="+_client_secret); } function setScript(string _script) only_owner{ script = _script; } - function clearAPICredentials() - only_owner { + function clearAPICredentials() only_owner { cred = ""; - credentials = ""; } function toString(bytes20 self) internal constant returns (string) { @@ -233,7 +183,7 @@ contract GitHubAPIOraclize is GitHubAPI, Owned, usingOraclize{ library QueryFactory { function newGitHubAPI() returns (GitHubAPI){ - return new GitHubAPIOraclize(); + return new GitHubOracle(); } } \ No newline at end of file diff --git a/contracts/src/GitHubRegisterEth.sol b/contracts/src/GitHubRegisterEth.sol deleted file mode 100644 index b67bd92..0000000 --- a/contracts/src/GitHubRegisterEth.sol +++ /dev/null @@ -1,160 +0,0 @@ -//Author: Ricardo Guilherme Schmidt <3esmit@gmail.com> -pragma solidity ^0.4.11; - -import "lib/oraclize/oraclizeAPI_0.4.sol"; -import "lib/ethereans/management/Owned.sol"; - -contract GitHubRegisterEth is Owned, usingOraclize{ - string private credentials = ""; - mapping (bytes32 => UserClaim) userClaim; //temporary db for oraclize user register queries - mapping (bytes32 => uint256) indexes; - mapping (uint256 => User) users; - - event RegisterUpdated(string name); - - //stores temporary data for oraclize user register request - struct UserClaim { - address sender; - string login; - } - - struct User { - address addr; - string login; - } - - function GitHubRegisterEth(){ - oraclize_setProof(proofType_TLSNotary | proofStorage_IPFS); - } - - function register(string _github_user, string _gistid) payable { - bytes32 ocid = oraclize_query("nested", _getQuery(_github_user, _gistid)); - userClaim[ocid] = UserClaim({sender: msg.sender, login: _github_user}); - } - - function getAddr(uint256 _id) public constant returns(address addr) { - return users[_id].addr; - } - - function getName(address _addr) public constant returns(string name){ - return users[indexes[sha3(_addr)]].login; - } - - function getAddr(string _name) public constant returns(address addr) { - return users[indexes[sha3(_name)]].addr; - } - - event OracleEvent(bytes32 myid, string result, bytes proof); - - //oraclize response callback - function __callback(bytes32 myid, string result, bytes proof) { - OracleEvent(myid,result,proof); - if (msg.sender != oraclize.cbAddress()){ - throw; - }else { - _register(myid, result); - } - } - - function _register(bytes32 myid, string result) internal { - bytes memory v = bytes(result); - uint8 pos = 0; - address addrLoaded; - string memory login; - uint256 userId; - (addrLoaded,pos) = getNextAddr(v,pos); - (login,pos) = getNextString(v,pos); - (userId,pos) = getNextUInt(v,pos); - if(userClaim[myid].sender == addrLoaded && sha3(userClaim[myid].login) == sha3(login)){ - RegisterUpdated(login); - if(users[userId].addr != 0x0){ - delete indexes[sha3(users[userId].login)]; - delete indexes[sha3(users[userId].addr)]; - } - indexes[sha3(addrLoaded)] = userId; - indexes[sha3(login)] = userId; - users[userId].addr = addrLoaded; - users[userId].login = login; - } - delete userClaim[myid]; //should always be deleted - } - - //owner management - function setAPICredentials(string _client_id, string _client_secret) only_owner { - credentials = strConcat("?client_id=",_client_id,"&client_secret=",_client_secret,""); - } - - function clearAPICredentials() only_owner { - credentials = ""; - } - - //internal helper functions - function _getQuery(string _github_user, string _gistid) internal constant returns (string){ - string memory a = strConcat("[identity] ${[URL] https://gist.githubusercontent.com/", _github_user,"/",_gistid,"/raw/registereth.txt}, ${[URL] json(https://api.github.com/gists/"); - return strConcat(a, _gistid, credentials, ").owner.[login,id]}",""); - } - - function getNextString(bytes _str, uint8 _pos) internal constant returns (string,uint8) { - uint8 start = 0; - uint8 end = 0; - uint strl =_str.length; - for (;strl > _pos; _pos++) { - if (_str[_pos] == '"'){ //Found quotation mark - if(_str[_pos-1] != '\\'){ //is not escaped - end = start == 0 ? 0: _pos; - start = start == 0 ? (_pos+1) : start; - if(end > 0) break; - } - } - } - bytes memory str = new bytes(end-start); - for(_pos=0; _pos _pos; _pos++) { - byte bp = _str[_pos]; - if (bp == ','){ //Find ends - _pos++; break; - }else if ((bp >= 48)&&(bp <= 57)){ //only ASCII numbers - val *= 10; - val += uint(bp) - 48; - } - } - return (val,_pos); - } - - function getNextAddr(bytes _str, uint8 _pos) internal constant returns (address, uint8){ - uint160 iaddr = 0; - uint strl =_str.length; - for(;strl > _pos; _pos++){ - byte bp = _str[_pos]; - if (bp == '0'){ - if (_str[_pos+1] == 'x'){ - for (_pos=_pos+2; _pos<2+2*20; _pos+=2){ - iaddr *= 256; - iaddr += (uint160(hexVal(uint160(_str[_pos])))*16+uint160(hexVal(uint160(_str[_pos+1])))); - } - _pos++; - break; - } - }else if (bp == ','){ - _pos++; - break; - } - } - return (address(iaddr),_pos); - } - - function hexVal(uint val) internal constant returns (uint){ - return val - (val < 58 ? 48 : (val < 97 ? 55 : 87)); - } - -} \ No newline at end of file diff --git a/contracts/src/GitHubRepositoryReg.sol b/contracts/src/GitHubRepositoryReg.sol new file mode 100644 index 0000000..6381c05 --- /dev/null +++ b/contracts/src/GitHubRepositoryReg.sol @@ -0,0 +1,81 @@ +//Author: Ricardo Guilherme Schmidt <3esmit@gmail.com> +pragma solidity ^0.4.11; + +import "GitHubAPIReg.sol"; +import "NameRegistry.sol"; +import "GitRepository.sol"; + +contract GitHubRepositoryReg is NameRegistry, GitHubAPIReg { + + mapping (uint256 => Repository) repositories; + + event UpdatedRepository(address addr, uint256 projectId, string full_name, string default_branch); + + struct Repository { + address addr; + string full_name; + string branch; + } + + function GitHubRepositoryReg(){ + oraclize_setProof(proofType_TLSNotary | proofStorage_IPFS); + } + + function setRepository(string _repository, bool create) payable only_owner{ + oraclize_query("URL", getQuery(_repository), create? 4000000 : 1000000); + } + + function getAddr(uint256 _id) public constant returns(address addr) { + return repositories[_id].addr; + } + + function getName(address _addr) public constant returns(string name){ + return repositories[indexes[sha3(_addr)]].login; + } + + function getAddr(string _name) public constant returns(address addr) { + return repositories[indexes[sha3(_name)]].addr; + } + + //oraclize response callback + function __callback(bytes32 myid, string result, bytes proof) { + OracleEvent(myid,result,proof); + if (msg.sender != oraclize.cbAddress()){ + throw; + }else { + _setRepository(myid, result); + } + } + + function _setRepository(bytes32 myid, string result) internal //[85743750, "ethereans/TheEtherian", "master"] + { + bytes memory v = bytes(result); + uint8 pos = 0; + string memory temp; + uint256 projectId; + (projectId,pos) = getNextUInt(v,pos); + string memory full_name; + (full_name,pos) = getNextString(v,pos); + string memory default_branch; + (default_branch,pos) = getNextString(v,pos); + address repoAddr = repositories[projectId].addr; + if(repoAddr == 0x0){ + repoAddr = address(GitFactory.newGitRepository(projectId, full_name, default_branch)); + indexes[sha3(repoAddr)] = projectId; + indexes[sha3(full_name)] = projectId; + NewRepository(repoAddr, projectId, full_name, default_branch); + repositories[projectId] = Repository(addr: repoAddr, full_name: full_name, default_branch: default_branch);| + }else{ + bytes32 _new = sha3(full_name); + bytes32 _old = sha3(repositories[projectId].full_name); + if(_new != _old){ + _updateIndex(_old, _new); + } + } + } + //internal helper functions + function _getQuery(string _repository) internal constant returns (string){ + return strConcat("json(https://api.github.com/repos/",_repository,credentials,").$.id,full_name,default_branch"); + } + +} \ No newline at end of file diff --git a/contracts/src/GitHubUserReg.sol b/contracts/src/GitHubUserReg.sol new file mode 100644 index 0000000..0f016dc --- /dev/null +++ b/contracts/src/GitHubUserReg.sol @@ -0,0 +1,81 @@ +//Author: Ricardo Guilherme Schmidt <3esmit@gmail.com> +pragma solidity ^0.4.11; + +import "GitHubAPIReg.sol"; +import "NameRegistry.sol"; + +contract GitHubUserReg is NameRegistry, GitHubAPIReg { + + mapping (bytes32 => UserClaim) userClaim; //temporary db for oraclize user register queries + mapping (uint256 => User) users; + + event RegisterUpdated(string name); + + //stores temporary data for oraclize user register request + struct UserClaim { + address sender; + string login; + } + + struct User { + address addr; + string login; + } + + function register(string _github_user, string _gistid) payable { + bytes32 ocid = oraclize_query("nested", _getQuery(_github_user, _gistid)); + userClaim[ocid] = UserClaim({sender: msg.sender, login: _github_user}); + } + + function getAddr(uint256 _id) public constant returns(address addr) { + return users[_id].addr; + } + + function getName(address _addr) public constant returns(string name){ + return users[indexes[sha3(_addr)]].login; + } + + function getAddr(string _name) public constant returns(address addr) { + return users[indexes[sha3(_name)]].addr; + } + + //oraclize response callback + function __callback(bytes32 myid, string result, bytes proof) { + OracleEvent(myid, result, proof); + if (msg.sender != oraclize.cbAddress()){ + throw; + }else { + _register(myid, result); + } + } + + function _register(bytes32 myid, string result) internal { + bytes memory v = bytes(result); + uint8 pos = 0; + address addrLoaded; + string memory login; + uint256 userId; + (addrLoaded,pos) = getNextAddr(v,pos); + (login,pos) = getNextString(v,pos); + (userId,pos) = getNextUInt(v,pos); + if(userClaim[myid].sender == addrLoaded && sha3(userClaim[myid].login) == sha3(login)){ + RegisterUpdated(login); + if(users[userId].addr != 0x0){ + delete indexes[sha3(users[userId].login)]; + delete indexes[sha3(users[userId].addr)]; + } + indexes[sha3(addrLoaded)] = userId; + indexes[sha3(login)] = userId; + users[userId].addr = addrLoaded; + users[userId].login = login; + } + delete userClaim[myid]; //should always be deleted + } + + //internal helper functions + function _getQuery(string _github_user, string _gistid) internal constant returns (string){ + string memory a = strConcat("[identity] ${[URL] https://gist.githubusercontent.com/", _github_user,"/",_gistid,"/raw/registereth.txt}, ${[URL] json(https://api.github.com/gists/"); + return strConcat(a, _gistid, credentials, ").owner.[login,id]}",""); + } + +} \ No newline at end of file diff --git a/contracts/src/NameRegistry.sol b/contracts/src/NameRegistry.sol new file mode 100644 index 0000000..e308ef0 --- /dev/null +++ b/contracts/src/NameRegistry.sol @@ -0,0 +1,5 @@ +contract NameRegistry{ + function getAddr(uint256 _id) public constant returns(address addr); + function getAddr(string _name) public constant returns(address addr); + function getName(address _addr) public constant returns(string name); +} \ No newline at end of file