-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Simon Mok
committed
Jul 8, 2018
0 parents
commit 69174e9
Showing
24 changed files
with
1,019 additions
and
0 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<title>Administrator</title> | ||
<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,700' rel='stylesheet' type='text/css'/> | ||
<link href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css' rel='stylesheet' type='text/css'/> | ||
<link rel="shortcut icon" type="image/png" href="images/certificate.ico"/> | ||
</head> | ||
<body class="container"> | ||
<div class="page-header"> | ||
<h1>Welcome, Administrator!</h1> | ||
</div> | ||
<a href="student-list.html" class="btn btn-success form-control" style="margin: 1em 0">Student Listing</a> | ||
<a href="issuer-list.html" class="btn btn-warning form-control" style="margin: 1em 0">Issuer Listing</a> | ||
<a href="index.html" class="btn">Back</a> | ||
</body> | ||
<script src="https://cdn.rawgit.com/ethereum/web3.js/develop/dist/web3.js"></script> | ||
<script src="https://code.jquery.com/jquery-3.1.1.slim.min.js"></script> | ||
</html> |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"port": 80, | ||
"open": false | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<title>Create Certificate</title> | ||
<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,700' rel='stylesheet' type='text/css'/> | ||
<link href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css' rel='stylesheet' type='text/css'/> | ||
<link rel="shortcut icon" type="image/png" href="images/certificate.ico"/> | ||
</head> | ||
<body class="container"> | ||
<div class="page-header"> | ||
<h1>Create Certificate</h1> | ||
</div> | ||
<form> | ||
<div class="alert alert-success" role="alert" style="display: none"> | ||
Certificate record created. | ||
</div> | ||
<div class="form-group"> | ||
<input type="text" class="form-control" id="course-title" placeholder="Course or programme title" required="required"/> | ||
</div> | ||
<div class="form-group"> | ||
<input type="text" class="form-control" id="address" placeholder="Student account address" required="required" pattern=".{42}" title="Address should have 42 characters"/> | ||
</div> | ||
<div class="form-group"> | ||
<input type="text" class="form-control" id="completion-date" onfocus="this.type='date'" onblur="this.type='text'" placeholder="Completion date" required="required"/> | ||
</div> | ||
<div class="form-group"> | ||
<input type="text" class="form-control" id="expiry-date" onfocus="this.type='date'" onblur="this.type='text'" placeholder="Expiry date" /> | ||
</div> | ||
<div class="alert alert-danger" role="alert" style="display: none"> | ||
</div> | ||
<input type="submit" class="btn btn-primary" value="Create Certificate"/> | ||
<a href="issuer-certificates.html" class="btn">Back</a> | ||
</form> | ||
</body> | ||
<script src="https://cdn.rawgit.com/ethereum/web3.js/develop/dist/web3.js"></script> | ||
<script src="https://code.jquery.com/jquery-3.1.1.slim.min.js"></script> | ||
<script src="js/certificate.js"></script> | ||
</html> |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,238 @@ | ||
pragma solidity ^0.4.23; | ||
|
||
contract Master { | ||
|
||
struct Certificate { | ||
address student; | ||
address issuer; | ||
string courseTitle; | ||
string completionDate; | ||
string expiryDate; | ||
} | ||
|
||
struct Student { | ||
string name; | ||
} | ||
|
||
struct Issuer { | ||
string issuerName; | ||
string logoUrl; | ||
string issuerAddress; | ||
} | ||
|
||
mapping (address => Student) private students; | ||
address[] private studentAddresses; | ||
|
||
mapping (address => Issuer) private issuers; | ||
address[] private issuerAddresses; | ||
|
||
Certificate[] private certificates; | ||
|
||
address private adminOwner; | ||
|
||
constructor() public { | ||
adminOwner = msg.sender; | ||
} | ||
|
||
// create new student (admin) | ||
function createStudent(address _address, string _name) public { | ||
|
||
// Check current user is admin | ||
require(adminOwner == msg.sender); | ||
|
||
// Check if account already exists | ||
validateAddress(_address); | ||
|
||
// Add a new student contract to students map | ||
students[_address] = Student({ | ||
name: _name | ||
}); | ||
|
||
// Add the address to studentAddresses array | ||
studentAddresses.push(_address); | ||
} | ||
|
||
function listStudentAddresses() public view returns (address[]) { | ||
|
||
return studentAddresses; | ||
} | ||
|
||
function listIssuerAddresses() public view returns (address[]) { | ||
|
||
return issuerAddresses; | ||
} | ||
|
||
function getStudentName(address _address) public view returns (string) { | ||
|
||
for (uint count = 0; count < studentAddresses.length; count++) { | ||
if (studentAddresses[count] == _address) { | ||
return students[_address].name; | ||
} | ||
} | ||
|
||
revert(); | ||
} | ||
|
||
function getIssuerName(address _address) public view returns (string) { | ||
|
||
for (uint count = 0; count < issuerAddresses.length; count++) { | ||
if (issuerAddresses[count] == _address) { | ||
return issuers[_address].issuerName; | ||
} | ||
} | ||
|
||
revert(); | ||
} | ||
|
||
function getIssuerDetails(address _address) public view returns (string, string, string) { | ||
|
||
for (uint count = 0; count < issuerAddresses.length; count++) { | ||
if (issuerAddresses[count] == _address) { | ||
Issuer storage issuer = issuers[_address]; | ||
return (issuer.issuerName, issuer.logoUrl, issuer.issuerAddress); | ||
} | ||
} | ||
|
||
revert(); | ||
} | ||
|
||
// create new issuer (admin) | ||
function createIssuer(address _address, string _name, string _issuerAddress, string _logoUrl) public { | ||
|
||
// Check current user is admin | ||
require(adminOwner == msg.sender); | ||
|
||
// Check if account already exists | ||
validateAddress(_address); | ||
|
||
// Add a new issuer contract to issuers map | ||
issuers[_address] = Issuer({ | ||
issuerName: _name, | ||
issuerAddress: _issuerAddress, | ||
logoUrl: _logoUrl | ||
}); | ||
|
||
// Add the address to issuerAddresses array | ||
issuerAddresses.push(_address); | ||
} | ||
|
||
function validateAddress(address _address) view private { | ||
|
||
// Check if account already exists | ||
for (uint count = 0; count < studentAddresses.length; count++) { | ||
if (studentAddresses[count] == _address) { | ||
revert(); | ||
} | ||
} | ||
|
||
for (count = 0; count < issuerAddresses.length; count++) { | ||
if (issuerAddresses[count] == _address) { | ||
revert(); | ||
} | ||
} | ||
|
||
if (_address == adminOwner) { | ||
revert(); | ||
} | ||
} | ||
|
||
// create new certificate (issuer) | ||
function createCertificate(address student, string courseTitle, string completionDate, string expiryDate) public { | ||
|
||
for (uint studentCount = 0; studentCount < studentAddresses.length; studentCount++) { | ||
if (studentAddresses[studentCount] == student) { | ||
for (uint issuerCount = 0; issuerCount < issuerAddresses.length; issuerCount++) { | ||
if (issuerAddresses[issuerCount] == msg.sender) { | ||
certificates.push(Certificate({ | ||
student: student, | ||
issuer: msg.sender, | ||
courseTitle: courseTitle, | ||
completionDate: completionDate, | ||
expiryDate: expiryDate | ||
})); | ||
return; | ||
} | ||
} | ||
} | ||
} | ||
|
||
revert(); | ||
} | ||
|
||
// Verify a certificate | ||
function verifyCertificate(address student, address issuer, string courseTitle) public view returns (uint) { | ||
|
||
for (uint count = 0; count < certificates.length; count++) { | ||
Certificate storage certificate = certificates[count]; | ||
if (certificate.student == student && certificate.issuer == issuer && equal(certificate.courseTitle, courseTitle)) { | ||
return count + 1; | ||
} | ||
} | ||
|
||
// validate expiry date | ||
|
||
return 0; | ||
} | ||
|
||
// Student to query his/her own certificates | ||
function getStudentCertificates() public view returns (uint[]) { | ||
|
||
uint[] memory studentCertificates = new uint[](certificates.length); | ||
uint index = 0; | ||
for (uint count = 0; count < certificates.length; count++) { | ||
if (certificates[count].student == msg.sender) { | ||
studentCertificates[index++] = count; | ||
} | ||
} | ||
return studentCertificates; | ||
} | ||
|
||
// Issuer to query issued certificates | ||
function getIssuerCertificates() public view returns (uint[]) { | ||
|
||
uint[] memory issuedCertificates = new uint[](certificates.length); | ||
uint index = 0; | ||
for (uint count = 0; count < certificates.length; count++) { | ||
if (certificates[count].issuer == msg.sender) { | ||
issuedCertificates[index++] = count; | ||
} | ||
} | ||
return issuedCertificates; | ||
} | ||
|
||
function getCertificateDetails(uint index) public view returns (string, string, string, string, string) { | ||
|
||
require(index < certificates.length); | ||
Certificate storage certificate = certificates[index]; | ||
return (issuers[certificate.issuer].issuerName, students[certificate.student].name, certificate.courseTitle, certificate.completionDate, certificate.expiryDate); | ||
} | ||
|
||
function compare(string _a, string _b) private pure returns (int) { | ||
|
||
bytes memory a = bytes(_a); | ||
bytes memory b = bytes(_b); | ||
uint minLength = a.length; | ||
if (b.length < minLength) minLength = b.length; | ||
for (uint i = 0; i < minLength; i ++) | ||
if (a[i] < b[i]) | ||
return -1; | ||
else if (a[i] > b[i]) | ||
return 1; | ||
if (a.length < b.length) | ||
return -1; | ||
else if (a.length > b.length) | ||
return 1; | ||
else | ||
return 0; | ||
} | ||
|
||
function equal(string _a, string _b) private pure returns (bool) { | ||
|
||
return compare(_a, _b) == 0; | ||
} | ||
|
||
// edit new student (admin / student) | ||
// edit new issuer (admin / issuer) | ||
// revoke new certificate (issuer) | ||
|
||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
console.log('Deploy started on ' + new Date()); | ||
console.log('Loading libraries'); | ||
|
||
var fs = require('fs'); | ||
var Web3 = require('web3'); | ||
var solc = require('solc'); | ||
var web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); | ||
|
||
console.log('Compiling Solidity contracts'); | ||
|
||
var compiled = solc.compile(fs.readFileSync('contracts/Master.sol').toString()); | ||
var abiDefinition = compiled.contracts[':Master'].interface; | ||
console.log('ABI Definition: ' + abiDefinition); | ||
|
||
var byteCode = compiled.contracts[':Master'].bytecode; | ||
var estimatedGas = web3.eth.estimateGas({data: byteCode}); | ||
console.log('Deploying contracts using estimated gas ' + estimatedGas); | ||
|
||
var contract = web3.eth.contract(JSON.parse(abiDefinition)).new(null, {data: byteCode, from: web3.eth.accounts[0], gas: estimatedGas}); | ||
|
||
new Promise((resolve) => setTimeout(resolve, 1000)).then(() => { | ||
|
||
console.log('Contract address: ' + contract.address); | ||
console.log('Writing dummy data'); | ||
console.log('Creating issuer'); | ||
contract.createIssuer(web3.eth.accounts[1], 'HKU', 'Pokfulam Road, HK', 'http://avuou.hku.hk/guestpage/HKUbw2.gif', {from: web3.eth.accounts[0], gas: contract.createIssuer.estimateGas(web3.eth.accounts[1], 'HKU', 'Pokfulam Road, HK', 'http://avuou.hku.hk/guestpage/HKUbw2.gif')}); | ||
console.log('Creating student'); | ||
contract.createStudent(web3.eth.accounts[2], 'Simon Chan', {from: web3.eth.accounts[0], gas: contract.createStudent.estimateGas(web3.eth.accounts[2], 'Simon Chan')}); | ||
console.log('Creating certificate'); | ||
web3.eth.defaultAccount = web3.eth.accounts[1]; | ||
contract.createCertificate(web3.eth.accounts[2], 'Introduction to Blockchain', '2018-07-01', '2028-08-31', {from: web3.eth.accounts[1], gas: contract.createCertificate.estimateGas(web3.eth.accounts[2], 'Introduction to Blockchain', '2018-07-01', '2028-08-31')}); | ||
console.log('Deploy complete at ' + new Date()); | ||
}); |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<title>Certificate Blockchain Apps</title> | ||
<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,700' rel='stylesheet' type='text/css'/> | ||
<link href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css' rel='stylesheet' type='text/css'/> | ||
<link rel="shortcut icon" type="image/png" href="images/certificate.ico"/> | ||
</head> | ||
<body class="container"> | ||
<div class="page-header"> | ||
<h1>Welcome to Certificate Blockchain Apps</h1> | ||
</div> | ||
<a href="search.html" class="btn btn-primary form-control" style="margin: 1em 0">Verify Certificate</a> | ||
<a href="student-certificates.html" class="btn btn-success form-control" style="margin: 1em 0">I am a student</a> | ||
<a href="issuer-certificates.html" class="btn btn-warning form-control" style="margin: 1em 0">I am an issuer</a> | ||
<a href="admin.html" class="btn btn-danger form-control" style="margin: 1em 0">I am the administrator</a> | ||
</body> | ||
<script src="https://cdn.rawgit.com/ethereum/web3.js/develop/dist/web3.js"></script> | ||
<script src="https://code.jquery.com/jquery-3.1.1.slim.min.js"></script> | ||
</html> |
Oops, something went wrong.