var express = require('express'); var router = express.Router(); var KyotoTycoon = require('kyoto-tycoon').KyotoTycoon; var CryptoJS = require('crypto-js'); var kt = new KyotoTycoon(); function randomString(length) { chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; var result = ''; for (var i = length; i > 0; --i) result += chars[Math.floor(Math.random() * chars.length)]; return result; } function mineBlock(block, requirement) { rand = ''; i = 0; while(CryptoJS.SHA512(JSON.stringify(block.content)).toString().substring(0, requirement.length) != requirement) { rand = randomString(32); block.content.rand = rand; i++; console.log(i + ': ' + rand + ' : ' + CryptoJS.SHA512(JSON.stringify(block.content)).toString()); } block.hash = CryptoJS.SHA512(JSON.stringify(block.content)).toString(); } function checkBlock(id, badId, goodId) { kt.get(id, function(err, data) { if(err) { console.log('Error getting block id ' + id); return -1; } else { kt.get(id - 1, function(err, prevData){ if(err) { console.log('Error getting block id ' + id - 1); } block = JSON.parse(data); if((CryptoJS.SHA512(JSON.stringify(block.content)).toString() === block.hash) && (block.content.prevhash === JSON.parse(prevData).hash)) { console.log('Block ' + block.content.id + ' is OK'); if(goodId) { goodId(block.content.id); } } else { console.log('Block ' + block.content.id + ' is bad'); if(badId) { badId(block.content.id); } } }); } }); } function checkChain() { j = 0; kt.status(':', async function (err, data) { if(err) { console.log('Error getting chain data.'); return -1; } else { for(i = 1; i < data.count; i++) { await checkBlock(i, function(id) { console.log('Handle badId: ' + id); deleteChain(id, data.count - 1); }, function(id) { console.log('Handle goodId: ' + id) }); } } }); } function deleteChain(firstId, lastId) { for(i = firstId; i <= lastId; i++) { console.log('Deleteing block id ' + i); kt.remove(i); } } function getLastTransactions(count, next) { result = []; j = 0; kt.status(':', async function(err, data) { if(err) { console.log('Error getting chain data.'); return -1; } for(i = data.count - count; i < data.count; i++) { result.push(new Promise((resolve, reject) => { kt.get(i, async function(err, block) { if(err) reject(err); resolve(JSON.parse(block)); }); })); } if(next) { next(await Promise.all(result)); } }); } /* GET home page. */ router.get('/', function(req, res, next) { getLastTransactions(15, async function(data) { await console.log(JSON.stringify(data)); breadcrumb = [{title:'home', url:'/', stat:'active'}] await res.render('index', { title: 'mCoin', data: data, breadcrumb: breadcrumb }); }); }); router.get('/new', function(req, res, next) { block = { content: { message: { from: 'Simona', to: 'Matjaz', amount: '200', timestamp: '1234', }, id: 1, previd: 0, prevhash: 'abc', rand: '', timestamp: '', unixtime: '', }, hash: '', difficulty: '', version: '0.01', }; difficulty = '000'; kt.status(':', function(err, data) { if(err) { console.log(err); } kt.get(data.count - 1, function(err, prevData) { if(err) { console.log(err); } const utcDate = new Date(); block.content.timestamp = utcDate.toUTCString(); block.content.unixtime = Math.floor(new Date().getTime() / 1000); block.content.prevhash = JSON.parse(prevData).hash; block.content.id = data.count; block.content.previd = data.count - 1; block.difficulty = difficulty; mineBlock(block, difficulty); console.log(JSON.stringify(block)); kt.set(block.content.id.toString(), JSON.stringify(block), function() { console.log('Block Written'); }); }); }); }); router.get('/check', function(req, res, next) { badBlock = 0; console.log('Checking the chain'); checkChain(); }); module.exports = router;