Skip to content

Instantly share code, notes, and snippets.

@alexpanasUCLA
Last active October 22, 2018 08:31
Show Gist options
  • Save alexpanasUCLA/af92c97dc8544dca3ebb2b697f09a4c3 to your computer and use it in GitHub Desktop.
Save alexpanasUCLA/af92c97dc8544dca3ebb2b697f09a4c3 to your computer and use it in GitHub Desktop.
Blockchain class
class Blockchain {
// Method 1: Initiate, and store blockchain in LevelDB
constructor(){
this.chain = level('./blockchaindata');
this.chain.put(0,JSON.stringify(Block.genesisBlock()))
}
// Method 2: Add new block to LevelDB
async addBlock(newBlock){
let minedBlock = await this.mineBlock(newBlock)
this.chain.put(minedBlock.height,JSON.stringify(minedBlock))
return minedBlock;
}
// Method 3: Create / Mine new block
async mineBlock(newBlock){
let l = await this.getBlockHeight();
let prev = await this.getBlock(l-1)
newBlock.height = l;
newBlock.time = new Date().getTime().toString().slice(0,-3);
newBlock.previousBlockHash = prev.hash;
newBlock.hash = SHA256(JSON.stringify(newBlock)).toString();
return newBlock;
}
// Method 4: Get the length of the existing chain
getBlockHeight() {
return new Promise((resolve,reject)=>{
let i = 0;
this.chain.createReadStream().on('data', function(data) {
i++;
}).on('error', function(err) {
reject('Unable to read data stream!', err)
}).on('end', function() {
resolve(i)
});
})
}
// Method 5: Get block from LevelDB with given height
getBlock(blockHeight){
return this.chain.get(blockHeight)
.then(block => JSON.parse(block))
.catch(err=>console.log('Can not get block',err))
}
// Method 6: Validate Block
async validateBlock(blockHeight){
// get block object
let block = await this.getBlock(blockHeight);
// get block hash
let blockHash = block.hash;
// remove block hash to test block integrity
block.hash = "";
// generate block hash
let validBlockHash = SHA256(JSON.stringify(block)).toString();
// Compare
if (blockHash===validBlockHash) {
return true;
} else {
console.log('Block #'+blockHeight+' invalid hash:\n'+blockHash+'<>'+validBlockHash);
return false;
}
}
//Method 7. Validate Blockchain.
async validateChain(){
let errorLog = [];
let lengthChain = await this.getBlockHeight();
for (let i = 0; i < lengthChain-1; i++) {
// validate block
if (!this.validateBlock(i)) errorLog.push(i);
// compare blocks hash link
let currentBlock = await this.getBlock(i);
let previousBlock = await this.getBlock(i+1)
let blockHash = currentBlock.hash;
let previousHash = previousBlock.previousBlockHash;
if (blockHash!==previousHash) {
errorLog.push(i);
}
}
if (errorLog.length>0) {
console.log('Block errors = ' + errorLog.length);
console.log('Blocks: '+errorLog);
} else {
console.log('No errors detected');
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment