Last active
April 20, 2018 14:23
-
-
Save PhABC/fa2c4053f895623d6c66e9e686bf388a to your computer and use it in GitHub Desktop.
This file contains hidden or 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.4.21; | |
/** | |
* @title Ownable | |
* @dev The Ownable contract has an owner address, and provides basic authorization control | |
* functions, this simplifies the implementation of "user permissions". | |
*/ | |
contract Ownable { | |
address public owner; | |
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); | |
/** | |
* @dev The Ownable constructor sets the original `owner` of the contract to the sender | |
* account. | |
*/ | |
function Ownable() public { | |
owner = msg.sender; | |
} | |
/** | |
* @dev Throws if called by any account other than the owner. | |
*/ | |
modifier onlyOwner() { | |
require(msg.sender == owner); | |
_; | |
} | |
/** | |
* @dev Allows the current owner to transfer control of the contract to a newOwner. | |
* @param newOwner The address to transfer ownership to. | |
*/ | |
function transferOwnership(address newOwner) public onlyOwner { | |
require(newOwner != address(0)); | |
OwnershipTransferred(owner, newOwner); | |
owner = newOwner; | |
} | |
} | |
//School registry | |
contract SchoolRegistry is Ownable { | |
struct School { | |
string name; | |
string website; | |
} | |
mapping(address => School) public schools; | |
/** | |
* @dev Allows the owner to edit a school | |
* @param _schoolAddress The address to be edited. | |
* @param _schoolName The name to be edited. | |
* @param _schoolWebsite The website to be edited. | |
*/ | |
function editSchool(address _schoolAddress, string _schoolName, string _schoolWebsite) public onlyOwner { | |
schools[_schoolAddress] = School(_schoolName, _schoolWebsite); | |
} | |
/** | |
* @dev Return school information | |
* @param _schoolAddress The address to retrieve information for. | |
*/ | |
function getSchoolInfo(address _schoolAddress) public view returns (string _name, string _website) { | |
return (schools[_schoolAddress].name , schools[_schoolAddress].website); | |
} | |
} | |
//Transcripts | |
contract Transcripts is Ownable { | |
SchoolRegistry public schoolRegistry; | |
mapping (address => bytes32[]) studentTranscripts; | |
event TranscriptAdded(address indexed _student, bytes32 _transcriptHash); | |
event SchoolRegistryUpdated(address _oldSchoolRegistry, address _newSchoolRegistry); | |
/** | |
* @dev Associate a hash entry with the student address | |
* @param _studentAddress The student address | |
* @param _studentTranscriptHash IPFS Hash | |
*/ | |
function record(address _studentAddress, bytes32 _studentTranscriptHash) public { | |
studentTranscripts[_studentAddress].push(_studentTranscriptHash); | |
emit TranscriptAdded(_studentAddress, _studentTranscriptHash); | |
} | |
/** | |
* @dev Get a array of hash associated with the student address | |
* @param _studentAddress The student address | |
* @return Array of IPFS hashes | |
*/ | |
function getTranscripts(address _studentAddress) public view returns (bytes32[]) { | |
return studentTranscripts[_studentAddress]; | |
} | |
/** | |
* @dev Set schoolRegistry address | |
* @param _schoolRegistry The school registry address | |
*/ | |
function setSchoolRegistry(SchoolRegistry _schoolRegistry) onlyOwner public { | |
require(address(_schoolRegistry) != 0x0); | |
emit SchoolRegistryUpdated(schoolRegistry, _schoolRegistry); | |
//Update school registry | |
schoolRegistry = _schoolRegistry; | |
} | |
/** | |
* @dev Return who signed the provided signature | |
* @param _hash hash that was signed | |
* @param _sig Signature | |
*/ | |
function getSignatureSigner(bytes32 _hash, bytes _sig) public view returns (address signer) { | |
//ECDSA variables | |
bytes32 r; | |
bytes32 s; | |
uint8 v; | |
//Extract ECDSA signature variables from `sig` | |
assembly { | |
r := mload(add(_sig, 32)) | |
s := mload(add(_sig, 64)) | |
v := byte(0, mload(add(_sig, 96))) | |
} | |
// Version of signature should be 27 or 28, but 0 and 1 are also possible versions | |
if (v < 27) { | |
v += 27; | |
} | |
//Adding prefix to hash to confirm to geth signature scheme | |
bytes32 prefixedHash = keccak256("\x19Ethereum Signed Message:\n32", _hash); | |
//Recover signer's address | |
signer = ecrecover( prefixedHash, v, r, s); | |
//Check if signer is expected school | |
return signer; | |
} | |
/** | |
* @dev Verify if a document was signed by a given school | |
* @param _ipfsHash Transcript IPFS hash | |
* @param _schoolAddress Address of expected school that signed Transcript | |
* @param _sig Signature | |
*/ | |
function isValidSignature(address _schoolAddress, bytes32 _ipfsHash, bytes _sig) public view returns (bool) { | |
return (getSignatureSigner(_ipfsHash, _sig) == _schoolAddress); | |
} | |
/** | |
* @dev Return the school information from the school that signed the transcript's hash | |
* @param _ipfsHash Transcript IPFS hash | |
* @param _sig Signature | |
*/ | |
function getSignerSchoolRegistryInfo(bytes32 _ipfsHash, bytes _sig) public view returns (string schoolName, string schoolWebsite) { | |
address signer = getSignatureSigner(_ipfsHash, _sig); | |
(schoolName, schoolWebsite) = schoolRegistry.getSchoolInfo(signer); | |
return (schoolName, schoolWebsite); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment