Skip to content

Commit

Permalink
Complete PubSub
Browse files Browse the repository at this point in the history
  • Loading branch information
15Dkatz committed Nov 12, 2018
1 parent ab272b2 commit 0110da6
Show file tree
Hide file tree
Showing 9 changed files with 1,680 additions and 143 deletions.
26 changes: 26 additions & 0 deletions average-work.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const Blockchain = require('./blockchain');

const blockchain = new Blockchain();

blockchain.addBlock({ data: 'initial' });

console.log('first block', blockchain.chain[blockchain.chain.length-1]);

let prevTimestamp, nextTimestamp, nextBlock, timeDiff, average;

const times = [];

for (let i=0; i<10000; i++) {
prevTimestamp = blockchain.chain[blockchain.chain.length-1].timestamp;

blockchain.addBlock({ data: `block ${i}`});
nextBlock = blockchain.chain[blockchain.chain.length-1];

nextTimestamp = nextBlock.timestamp;
timeDiff = nextTimestamp - prevTimestamp;
times.push(timeDiff);

average = times.reduce((total, num) => (total + num))/times.length;

console.log(`Time to mine block: ${timeDiff}ms. Difficulty: ${nextBlock.difficulty}. Average time: ${average}ms`);
}
3 changes: 2 additions & 1 deletion block.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const hexToBinary = require('hex-to-binary');
const { GENESIS_DATA, MINE_RATE } = require('./config');
const cryptoHash = require('./crypto-hash');

Expand Down Expand Up @@ -26,7 +27,7 @@ class Block {
timestamp = Date.now();
difficulty = Block.adjustDifficulty({ originalBlock: lastBlock, timestamp });
hash = cryptoHash(timestamp, lastHash, data, nonce, difficulty);
} while (hash.substring(0, difficulty) !== '0'.repeat(difficulty));
} while (hexToBinary(hash).substring(0, difficulty) !== '0'.repeat(difficulty));

return new this({ timestamp, lastHash, data, difficulty, nonce, hash });
}
Expand Down
3 changes: 2 additions & 1 deletion block.test.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const hexToBinary = require('hex-to-binary');
const Block = require('./block');
const { GENESIS_DATA, MINE_RATE } = require('./config');
const cryptoHash = require('./crypto-hash');
Expand Down Expand Up @@ -67,7 +68,7 @@ describe('Block', () => {
});

it('sets a `hash` that matches the difficulty criteria', () => {
expect(minedBlock.hash.substring(0, minedBlock.difficulty))
expect(hexToBinary(minedBlock.hash).substring(0, minedBlock.difficulty))
.toEqual('0'.repeat(minedBlock.difficulty));
});

Expand Down
4 changes: 3 additions & 1 deletion blockchain.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,16 @@ class Blockchain {

for (let i=1; i<chain.length; i++) {
const { timestamp, lastHash, hash, nonce, difficulty, data } = chain[i];

const actualLastHash = chain[i-1].hash;
const lastDifficulty = chain[i-1].difficulty;

if (lastHash !== actualLastHash) return false;

const validatedHash = cryptoHash(timestamp, lastHash, data, nonce, difficulty);

if (hash !== validatedHash) return false;

if (Math.abs(lastDifficulty - difficulty) > 1) return false;
}

return true;
Expand Down
20 changes: 20 additions & 0 deletions blockchain.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const Blockchain = require('./blockchain');
const Block = require('./block');
const cryptoHash = require('./crypto-hash');

describe('Blockchain', () => {
let blockchain, newChain, originalChain;
Expand Down Expand Up @@ -58,6 +59,25 @@ describe('Blockchain', () => {
});
});

describe('and the chain contains a block with a jumped difficulty', () => {
it('returns false', () => {
const lastBlock = blockchain.chain[blockchain.chain.length-1];
const lastHash = lastBlock.hash;
const timestamp = Date.now();
const nonce = 0;
const data = [];
const difficulty = lastBlock.difficulty - 3;
const hash = cryptoHash(timestamp, lastHash, difficulty, nonce, data);
const badBlock = new Block({
timestamp, lastHash, hash, nonce, difficulty, data
});

blockchain.chain.push(badBlock);

expect(Blockchain.isValidChain(blockchain.chain)).toBe(false);
});
});

describe('and the chain does not contain any invalid blocks', () => {
it('returns true', () => {
expect(Blockchain.isValidChain(blockchain.chain)).toBe(true);
Expand Down
54 changes: 54 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
const bodyParser = require('body-parser');
const express = require('express');
const request = require('request');
const Blockchain = require('./blockchain');
const PubSub = require('./pubsub');

const app = express();
const blockchain = new Blockchain();
const pubsub = new PubSub({ blockchain });

const DEFAULT_PORT = 3000;
const ROOT_NODE_ADDRESS = `http://localhost:${DEFAULT_PORT}`;

app.use(bodyParser.json());

app.get('/api/blocks', (req, res) => {
res.json(blockchain.chain);
});

app.post('/api/mine', (req, res) => {
const { data } = req.body;

blockchain.addBlock({ data });

pubsub.broadcastChain();

res.redirect('/api/blocks');
});

const syncChains = () => {
request({ url: `${ROOT_NODE_ADDRESS}/api/blocks` }, (error, response, body) => {
if (!error && response.statusCode === 200) {
const rootChain = JSON.parse(body);

console.log('replace chain on a sync with', rootChain);
blockchain.replaceChain(rootChain);
}
});
};

let PEER_PORT;

if (process.env.GENERATE_PEER_PORT === 'true') {
PEER_PORT = DEFAULT_PORT + Math.ceil(Math.random() * 1000);
}

const PORT = PEER_PORT || DEFAULT_PORT;
app.listen(PORT, () => {
console.log(`listening at localhost:${PORT}`);

if (PORT !== DEFAULT_PORT) {
syncChains();
}
});
Loading

0 comments on commit 0110da6

Please sign in to comment.