Skip to content

Instantly share code, notes, and snippets.

@PhABC
Last active April 20, 2018 14:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save PhABC/fa2c4053f895623d6c66e9e686bf388a to your computer and use it in GitHub Desktop.
Save PhABC/fa2c4053f895623d6c66e9e686bf388a to your computer and use it in GitHub Desktop.
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