/* * Organization: Fraunhofer AISEC * Author: Christof Ferreira Torres * Date: 06.03.2018 */ pragma solidity ^0.4.18; import "./libs/Ownable.sol"; import "./libs/Destructible.sol"; /* Interface with its functions to the IdentityMgmt contract */ contract IdentityMgmtInterface { function isIdentityMgmt() public constant returns (bool); function isAccreditedCertifier(address certifier) public constant returns (bool); function getInstitutionFromCertifier(address certifier) public constant returns (address); function getInstitutionProfile(address institution) public constant returns (bytes32); } contract CertMgmt is Ownable, Destructible { // Structure of a certificate stored in the blockchain struct Certificate { address institution; uint256 startingDate; uint256 endingDate; uint256 onHold; } // Mapping SHA256 certificate hash to certifacte struct mapping(bytes32 => Certificate) private certificates; // Interface to access an external IdentityMgmt contract IdentityMgmtInterface private identityMgmt; // Log events event CertificateStored( address caller, bytes32 hash, address institution, uint256 startingDate, uint256 endingDate, uint256 timestamp); event CertificatePermanentlyRevoked( address caller, address institution, bytes32 hash, uint256 timestamp); event CertificateTemporarilyRevoked( address caller, address institution, bytes32 hash, uint256 timestamp); event CertificateReactivated( address caller, address institution, bytes32 hash, uint256 timestamp); /* Constructor */ function CertMgmt(address identityMgmtAddress) public { updateIdentityMgmtAddress(identityMgmtAddress); } /* Standard functions in order to mange money tranfers and self destruction */ // Default function which basically does nothing except receiving money function() public payable {} // Removes the storage and code of the smart contract from the blockchain and transfers // the funds to a given destination. Can only be called by the owner. function destroy(address destination) onlyOwner external { require(destination != address(0)); selfdestruct(destination); } // Transfer all the current funds to a given destionation. Can only be called by the owner. function transfer(address destination) onlyOwner external payable { require(destination != address(0)); destination.transfer(this.balance); } /* Contract functions */ // Replaces the IdentityMgmt contract address with a new one. Can only be called // by the owner. function updateIdentityMgmtAddress(address identityMgmtAddress) public onlyOwner { require(identityMgmtAddress != address(0)); IdentityMgmtInterface candidateContract = IdentityMgmtInterface(identityMgmtAddress); // NOTE: verify that a contract is what we expect // https://github.com/Lunyr/crowdsale-contracts/blob/ // cfadd15986c30521d8ba7d5b6f57b4fefcc7ac38/contracts/LunyrToken.sol#L117 require(candidateContract.isIdentityMgmt()); // Set the new contract address identityMgmt = candidateContract; } // Stores a given certficate in the registry by associating a starting date and // ending date with a hash. Can only be called by an accredited certfier. function storeCertificate(bytes32 hash, uint256 startingDate, uint256 endingDate) public { require(identityMgmt.isAccreditedCertifier(msg.sender)); require(certificates[hash].institution == address(0)); require(endingDate > startingDate); address institution = identityMgmt.getInstitutionFromCertifier(msg.sender); certificates[hash] = Certificate(institution, startingDate, endingDate, 0); CertificateStored(msg.sender, hash, institution, startingDate, endingDate, now); } // Removes a given certifcate association (via its hash) from the blockchain. Can // only be called by an accredited certfier that is associated with the institution // that stored certificate. function permanentlyRevokeCertificate(bytes32 hash) public { require(identityMgmt.isAccreditedCertifier(msg.sender)); address institution = identityMgmt.getInstitutionFromCertifier(msg.sender); require(institution == certificates[hash].institution); delete certificates[hash]; CertificatePermanentlyRevoked(msg.sender, institution, hash, now); } // Sets the "onHold" flag with the current timestamp in order to mark a given certificate // as temporarily revoked. Can only be called by an accredited certfier that is associated // with the institution that stored certificate. function temporarilyRevokeCertificate(bytes32 hash) public { require(identityMgmt.isAccreditedCertifier(msg.sender)); address institution = identityMgmt.getInstitutionFromCertifier(msg.sender); require(institution == certificates[hash].institution); require(certificates[hash].onHold == 0); uint256 currentTimestamp = now; certificates[hash].onHold = currentTimestamp; CertificateTemporarilyRevoked(msg.sender, institution, hash, currentTimestamp); } // Removes the "onHold" flag in order to abolish the temporary revocation. Can only be // called by an accredited certfier that is associated with the institution that // stored certificate. function reactivateCertificate(bytes32 hash) public { require(identityMgmt.isAccreditedCertifier(msg.sender)); address institution = identityMgmt.getInstitutionFromCertifier(msg.sender); require(institution == certificates[hash].institution); require(certificates[hash].onHold > 0); certificates[hash].onHold = 0; CertificateReactivated(msg.sender, institution, hash, now); } // Returns information about a given certifacte and its validity. Can be called by anyone. function getCertificate(bytes32 hash) public constant returns (address, bytes32, uint256, uint256, uint256, bool) { bytes32 institutionProfile = identityMgmt.getInstitutionProfile(certificates[hash].institution); bool valid = false; if (certificates[hash].institution != address(0) && now < certificates[hash].endingDate && certificates[hash].onHold == 0) { valid = true; } return (certificates[hash].institution, institutionProfile, certificates[hash].startingDate, ertificates[hash].endingDate, certificates[hash].onHold, valid); } }