Created
July 29, 2019 12:39
-
-
Save fengkiej/9bac2f6cc32cd9c4df01fda33ef96daa to your computer and use it in GitHub Desktop.
Created using remix-ide: Realtime Ethereum Contract Compiler and Runtime. Load this file by pasting this gists URL or ID at https://remix.ethereum.org/#version=soljson-v0.5.2+commit.1df8f40c.js&optimize=false&gist=
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; | |
pragma experimental ABIEncoderV2; | |
//self sign | |
import "./ConsensusContract.sol"; | |
contract CertificationContract { | |
enum CertificationType { | |
NONE, N2A, A2A, A2U | |
} | |
enum AccountType { | |
NONE, NATIONAL_LAB, ACCREDITED_LAB, USER | |
} | |
struct Account { | |
string name; | |
AccountType accountType; | |
uint256[] certHashes; | |
} | |
struct Certificate { | |
string accrediationNo; | |
string calibrationCertNo; | |
string[2] uri; | |
address issuedBy; | |
address issuedTo; | |
uint256 issuedOn; | |
uint256 expiredOn; | |
uint256 parentCertificate; | |
CertificationType certType; | |
} | |
ConsensusContract consensusContract; | |
bool setup; | |
string public measurementType; | |
mapping (uint256 => Certificate) public certs; | |
mapping (address => Account) public accounts; | |
modifier onlyByConsensus() { | |
require(msg.sender == address(consensusContract)); | |
_; | |
} | |
modifier onlyOnce() { | |
require(setup == false); | |
_; | |
} | |
constructor(string memory _measurementType) public { | |
measurementType = _measurementType; | |
} | |
function setupConsensusContract(ConsensusContract _consensusContract) public onlyOnce { | |
consensusContract = _consensusContract; | |
setup = true; | |
} | |
function registerCertificate(uint256 _certificateHash, string memory _accrediationNumber, string memory _calibrationCertNumber, | |
string[2] memory _uri, address _to, uint256 _expiredOn, CertificationType _certType, uint256 _signUsingCertHash) public { | |
require(accounts[msg.sender].accountType == AccountType.NATIONAL_LAB || accounts[msg.sender].accountType == AccountType.ACCREDITED_LAB); | |
require(_expiredOn >= now); | |
if(accounts[msg.sender].accountType != AccountType.NATIONAL_LAB) { | |
require(isValid(_signUsingCertHash)); | |
require(certs[_signUsingCertHash].issuedTo == msg.sender); | |
} | |
if(_certType == CertificationType.N2A) { | |
require(accounts[msg.sender].accountType == AccountType.NATIONAL_LAB); | |
require(accounts[_to].accountType == AccountType.ACCREDITED_LAB); | |
_registerCertificate(_certificateHash, _accrediationNumber, _calibrationCertNumber, _uri, _to, _expiredOn, _certType, _signUsingCertHash); | |
} else if (_certType == CertificationType.A2A) { | |
require(accounts[msg.sender].accountType == AccountType.ACCREDITED_LAB); | |
require(accounts[_to].accountType == AccountType.ACCREDITED_LAB); | |
_registerCertificate(_certificateHash, _accrediationNumber, _calibrationCertNumber, _uri, _to, _expiredOn, _certType, _signUsingCertHash); | |
} else if (_certType == CertificationType.A2U) { | |
require(accounts[msg.sender].accountType == AccountType.ACCREDITED_LAB); | |
require(accounts[_to].accountType == AccountType.USER); | |
_registerCertificate(_certificateHash, _accrediationNumber, _calibrationCertNumber, _uri, _to, _expiredOn, _certType, _signUsingCertHash); | |
} else { | |
revert(); | |
} | |
} | |
function _registerCertificate(uint256 _certificateHash, string memory _accrediationNumber, string memory _calibrationCertNumber, | |
string[2] memory _uri, address _to, uint256 _expiredOn, CertificationType _certType, uint256 _signUsingCertHash) internal { | |
Certificate memory cert = Certificate(_accrediationNumber, _calibrationCertNumber, _uri, msg.sender, _to, now, _expiredOn, _signUsingCertHash, _certType); | |
require(certs[_certificateHash].issuedBy == address(0)); | |
certs[_certificateHash] = cert; | |
accounts[_to].certHashes.push(_certificateHash); | |
} | |
function registerAccount(string memory _name, AccountType _accountType) public { | |
require(accounts[msg.sender].accountType == AccountType.NONE); | |
require(_accountType != AccountType.NATIONAL_LAB); | |
uint256[] memory empty; | |
accounts[msg.sender] = Account(_name, _accountType, empty); | |
} | |
function registerNationalLab(string calldata _name, address _newNationalLab) external onlyByConsensus { | |
accounts[_newNationalLab].accountType = AccountType.NATIONAL_LAB; | |
accounts[_newNationalLab].name = _name; | |
} | |
function getAccountCertificates() public view returns (uint256[] memory) { | |
return accounts[msg.sender].certHashes; | |
} | |
function getValidAccountCertificates() public view returns (uint256[] memory) { | |
/*uint256[] memory certList = accounts[msg.sender].certHashes; | |
//uint256[] memory result = new uint256[](certList.length); | |
for(uint256 i = 0; i < certList.length; i++) { | |
if(isValid(certList[i])) result[i] = certList[i]; | |
} | |
return result;*/ | |
} | |
function getParentCertificate(uint256 _hash) public view returns (uint256) { | |
return certs[_hash].parentCertificate; | |
} | |
function isValid(uint256 _hash) public view returns (bool) { | |
Certificate memory cert = certs[_hash]; | |
return (now < cert.expiredOn || now > cert.issuedOn); | |
} | |
function getNow() public view returns (uint256) { | |
return now; | |
} | |
function traceCert(uint256 _hash) public view returns (uint256[8] memory) { | |
uint8 loc = 0; | |
Account memory issuer = accounts[certs[getParentCertificate(_hash)].issuedBy]; | |
uint256[8] memory parentCertificates; | |
parentCertificates[loc]= _hash; | |
while(issuer.accountType != AccountType.NATIONAL_LAB) { | |
_hash = getParentCertificate(_hash); | |
issuer = accounts[certs[getParentCertificate(_hash)].issuedBy]; | |
parentCertificates[++loc] = _hash; | |
} | |
return parentCertificates; | |
} | |
function revokeCertificate(uint256 _hash) public { | |
Certificate memory cert = certs[_hash]; | |
require(msg.sender == cert.issuedBy); | |
delete certs[_hash]; | |
} | |
} |
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; | |
pragma experimental ABIEncoderV2; | |
//remove member function | |
//no double voting | |
//new consortium for future work | |
import "./CertificationContract.sol"; | |
contract ConsensusContract { | |
struct Member { | |
string name; | |
uint256 consortiumID; | |
} | |
struct Proposal { | |
address newMemberAddress; | |
string name; | |
uint256 consortiumID; | |
uint256 confirmationsRequired; | |
} | |
CertificationContract certificationContract; | |
//consortiums maps from consortiumID to consortiumName, it starts at 1 | |
mapping (uint256 => string) public consortiums; | |
mapping (address => Member) public consortiumMembers; | |
mapping (uint256 => Proposal) public proposals; | |
uint256 lastProposalID; | |
uint256[8] public numberofConsortiumMembers; | |
modifier onlyConsortiumMember(uint256 consortiumID) { | |
require(consortiumMembers[msg.sender].consortiumID == consortiumID); | |
_; | |
} | |
constructor(CertificationContract _certificationContract, address[] memory _seedMemberAddresses, string[] memory _seedMemberNames,uint256[] memory _seedMemberConsortiums) public { | |
require(_seedMemberAddresses.length == _seedMemberNames.length); | |
require(_seedMemberAddresses.length == _seedMemberConsortiums.length); | |
certificationContract = _certificationContract; | |
certificationContract.setupConsensusContract(this); | |
for(uint256 i = 0; i < _seedMemberAddresses.length; i++) { | |
_addNewMember(_seedMemberAddresses[i], _seedMemberNames[i], _seedMemberConsortiums[i]); | |
} | |
} | |
function proposeNewMember(address _newMemberAddress, string memory _name, uint256 _consortiumID) public onlyConsortiumMember(_consortiumID) { | |
require(_consortiumID != 0); | |
Proposal memory newProposal = Proposal(_newMemberAddress, _name, _consortiumID, numberofConsortiumMembers[_consortiumID]); | |
proposals[lastProposalID] = newProposal; | |
lastProposalID++; | |
} | |
function confirmProposal(uint256 _proposalID) public { | |
require(proposals[_proposalID].consortiumID == consortiumMembers[msg.sender].consortiumID); | |
proposals[_proposalID].confirmationsRequired--; | |
if(proposals[_proposalID].confirmationsRequired == 0 && proposals[_proposalID].newMemberAddress != address(0)) { | |
_addNewMember(proposals[_proposalID].newMemberAddress, proposals[_proposalID].name, proposals[_proposalID].consortiumID); | |
} | |
} | |
function _addNewMember(address _newMemberAddress, string memory _name, uint256 _consortiumID) internal { | |
Member memory newMember = Member(_name, _consortiumID); | |
consortiumMembers[_newMemberAddress] = newMember; | |
numberofConsortiumMembers[_consortiumID]++; | |
certificationContract.registerNationalLab(_name, _newMemberAddress); | |
} | |
} |
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
//assumption 1: National Lab issuers are selected by consensus on MultisigConsensus.sol. | |
//assumption 2: ////reviseEach issuer can only have one certificate, it is replacable if the issuer releases it's current certificate. | |
//assumption 3: Issuing party may revoke a certificate. | |
//assumption 4: The validity of a certificate trickles down. --revise | |
//assumption 5: Every type of issuer can issue certs. | |
//assumption 6: uri file visibility is determined on the server. | |
//assumption 7: Issuer can't issue beyond it's current expiredOn. | |
//assumption 8: ACCREDITED_LAB must have accreditaion number | |
//asssmption 9: one deployed contract can support 1 measurement | |
//notes: national lab is part of what? non-issuer indexing per benua | |
//print: issuance, url[2], validity, company name, expiry, calibrationno, accreditaion no, | |
//tracevalidity | |
pragma solidity ^0.5.1; | |
contract CalibrationCertification { | |
address multisigConsensusContractAddress; | |
enum IssuerType { | |
NONE, NATIONAL_LAB, ACCREDITED_LAB, USER | |
} | |
enum CertificationType { | |
NONE, N2A, A2A, A2U | |
} | |
struct Issuer { | |
string name; | |
IssuerType issuerType; | |
uint256 certHash; | |
} | |
struct Certificate { | |
string accrediationNo; | |
string calibrationCertNo; | |
string uri; | |
address issuedBy; | |
address issuedTo; | |
uint256 issuedOn; | |
uint256 expiredOn; | |
CertificationType certType; | |
} | |
mapping (uint256 => Certificate) certs; | |
mapping (address => Issuer) public issuers; | |
modifier onlyByConsensus() { | |
require(msg.sender == multisigConsensusContractAddress); | |
_; | |
} | |
constructor(address _multisigConsensusContractAddress) public { | |
multisigConsensusContractAddress = _multisigConsensusContractAddress; | |
} | |
function registerCertificate(uint256 _hash, string memory _uri, address _to, | |
uint256 _expiredOn, CertificationType _certType) public { | |
require(isValid(issuers[msg.sender].certHash)); | |
require(issuers[_to].certHash == 0); | |
require(_expiredOn < certs[(issuers[msg.sender].certHash)].expiredOn); | |
if(_certType == CertificationType.N2A) { | |
require(issuers[msg.sender].issuerType == IssuerType.NATIONAL_LAB); | |
_registerCertificate(_hash, _uri, _to, now, _expiredOn, _certType); | |
_registerCertToReceiver(_to, IssuerType.ACCREDITED_LAB, _hash); | |
} | |
else if(_certType == CertificationType.A2A) { | |
require(issuers[msg.sender].issuerType == IssuerType.ACCREDITED_LAB); | |
_registerCertificate(_hash, _uri, _to, now, _expiredOn, _certType); | |
_registerCertToReceiver(_to, IssuerType.ACCREDITED_LAB, _hash); | |
} | |
else if(_certType == CertificationType.A2U) { | |
require(issuers[msg.sender].issuerType == IssuerType.ACCREDITED_LAB); | |
_registerCertificate(_hash, _uri, _to, now, _expiredOn, _certType); | |
_registerCertToReceiver(_to, IssuerType.USER, _hash); | |
} | |
else { | |
revert(); | |
} | |
} | |
function revokeCertificate(uint256 _hash) public { | |
Certificate memory cert = certs[_hash]; | |
require(msg.sender == cert.issuedBy); | |
issuers[cert.issuedTo].certHash = 0; | |
delete certs[_hash]; | |
} | |
function isExpired(uint256 _hash) public view returns (bool) { | |
Certificate memory cert = certs[_hash]; | |
return now > cert.expiredOn; | |
} | |
function getParentIssuer(uint256 _hash) internal view returns (address) { | |
return certs[_hash].issuedBy; | |
} | |
function traceCert(uint256 _hash) public view returns (uint256[8] memory) { | |
uint8 loc = 0; | |
Issuer memory issuer = issuers[getParentIssuer(_hash)]; | |
uint256[8] memory parentCertificates; | |
parentCertificates[loc]= _hash; | |
while(issuer.issuerType != IssuerType.NATIONAL_LAB) { | |
_hash = issuer.certHash; | |
issuer = issuers[getParentIssuer(_hash)]; | |
parentCertificates[++loc] = _hash; | |
} | |
return parentCertificates; | |
} | |
function _registerCertificate(uint256 _hash, string memory _uri, address _to, uint256 _issuedOn, uint256 _expiredOn, CertificationType _certType) internal { | |
Certificate memory cert = Certificate(" ", " ", _uri, msg.sender, _to, _issuedOn, _expiredOn, _certType); | |
require(certs[_hash].issuedBy == address(0)); | |
certs[_hash] = cert; | |
} | |
function registerAsIssuer(string memory _name) public { | |
issuers[msg.sender] = Issuer(_name, IssuerType.NONE, 0); | |
} | |
function _registerCertToReceiver(address _to, IssuerType _issuerType, uint256 _hash) public { | |
require(bytes(issuers[_to].name).length > 0); | |
issuers[_to].issuerType = _issuerType; | |
issuers[_to].certHash = _hash; | |
} | |
function issuerName(address _addr) public view returns (string memory) { | |
return issuers[_addr].name; | |
} | |
function renewCertificate(uint256 _hash, uint256 _expiredOn) public { | |
require(certs[_hash].issuedBy == msg.sender); | |
certs[_hash].expiredOn = _expiredOn; | |
} | |
function registerNationalLab(address _newNationalLab) public onlyByConsensus { | |
require(bytes(issuers[_newNationalLab].name).length > 0); | |
issuers[_newNationalLab].issuerType = IssuerType.NATIONAL_LAB; | |
} | |
function isValid(uint256 _hash) public view returns (bool) { | |
bool parentValidity = true; | |
Issuer memory issuer = issuers[getParentIssuer(_hash)]; | |
Certificate memory cert; | |
bool certValidity = !isExpired(_hash) && (certs[_hash].issuedOn > 0); | |
while(issuer.issuerType != IssuerType.NATIONAL_LAB) { | |
_hash = issuer.certHash; | |
cert = certs[_hash]; | |
if(isExpired(_hash) || cert.issuedOn == 0) { | |
parentValidity = false; | |
break; | |
} | |
issuer = issuers[getParentIssuer(_hash)]; | |
} | |
return certValidity && parentValidity; | |
} | |
function issuerCertHash(address _issuer) public view returns (uint256) { | |
return issuers[_issuer].certHash; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment