Project_1_v2_boilerplate Code

Ace your homework & exams now with Quizwiz!

Blockchain.js * This method will check for the height of the chain and if there isn't a Genesis Block it will create it. * You should use the `addBlock(block)` to create the Genesis Block * Passing as a data `{data: 'Genesis Block'}`

async initializeChain() { if( this.height === -1){ let block = new BlockClass.Block({data: 'Genesis Block'}); await this._addBlock(block); } }

Blockchain.js * _addBlock(block) will store a block in the chain * @param {*} block * The method will return a Promise that will resolve with the block added * or reject if an error happen during the execution. * You will need to check for the height to assign the `previousBlockHash`, * assign the `timestamp` and the correct `height`...At the end you need to * create the `block hash` and push the block into the chain array. Don't for get * to update the `this.height` * Note: the symbol `_` in the method name indicates in the javascript convention * that this method is a private method.

_addBlock(block) { let self = this; return new Promise(async (resolve, reject) => { let blockObj = block; let height = await self.getChainHeight(); blockObj.time = new Date().getTime().toString().slice(0,-3); if(height >= 0){ blockObj.height = height + 1; let previousBlock = self.chain[self.height]; blockObj.previousBlockHash = previousBlock.hash; // Verify signature blockObj.hash = SHA256(JSON.stringify(blockObj)).toString(); self.chain.push(blockObj); self.height = self.chain.length -1; resolve(blockObj); } else { // Only for the Genesis Block blockObj.height = height + 1; blockObj.hash = SHA256(JSON.stringify(blockObj)).toString(); self.chain.push(blockObj); self.height = self.chain.length - 1; resolve(blockObj); } }); }

Blockchain.js * Constructor of the class, you will need to setup your chain array and the height * of your chain (the length of your chain array). * Also everytime you create a Blockchain class you will need to initialized the chain creating * the Genesis Block. * The methods in this class will always return a Promise to allow client applications or * other backends to call asynchronous functions.

constructor() { this.chain = []; this.height = -1; this.initializeChain(); }

Block.js // Constructor - argument data will be the object containing the transaction data // Hash of the block // Block Height (consecutive number of each block) // Will contain the transactions stored in the block, by default it will encode the data // Timestamp for the Block creation // Reference to the previous Block Hash

constructor(data){ this.hash = null; this.height = 0; this.body = Buffer.from(JSON.stringify(data)).toString('hex'); this.time = 0; this.previousBlockHash = null; }

Block.js * Auxiliary Method to return the block body (decoding the data) * Steps: * * 1. Use hex2ascii module to decode the data * 2. Because data is a javascript object use JSON.parse(string) to get the Javascript Object * 3. Resolve with the data and make sure that you don't need to return the data for the `genesis block` * or Reject with an error.

getBData() { let dataEncoded = this.body; // Getting the encoded data saved in the Block let dataJson = hex2ascii(dataEncoded); // Decoding the data to retrieve the JSON representation of the object let data = JSON.parse(dataJson); // Parse the data to an object to be retrieve. if( data && this.height > 0){ return data; // Resolve with the data } } }

Blockchain.js * This method will return a Promise that will resolve with the Block * with the hash passed as a parameter. * Search on the chain array for the block that has the hash. * @param {*} hash

getBlockByHash(hash) { let self = this; return new Promise((resolve, reject) => { let block = self.chain.filter(p => p.hash === hash)[0]; if(block){ resolve(block); } else { resolve(null); } }); }

Blockchain.js * This method will return a Promise that will resolve with the Block object * with the height equal to the parameter `height` * @param {*} height

getBlockByHeight(height) { let self = this; return new Promise((resolve, reject) => { let block = self.chain.filter(p => p.height === height)[0]; if(block){ resolve(block); } else { resolve(null); } }); }

Blockchain.js * Utility method that return a Promise that will resolve with the height of the chain

getChainHeight() { return new Promise((resolve, reject) => { resolve(this.height); }); }

Blockchain.js * This method will return a Promise that will resolve with an array of Stars objects existing in the chain * and are belongs to the owner with the wallet address passed as parameter. * @param {*} address

getStarsByWalletAddress (address) { let self = this; let stars = []; return new Promise((resolve, reject) => { self.chain.forEach((b) => { let data = b.getBData(); if(data){ if (data.owner === address){ stars.push(data); } } }); resolve(stars); }); }

Block.js // Exposing the Block class as a module

module.exports.Block = Block;

Blockchain.js * The requestMessageOwnershipVerification(address) method * will allow you to request a message that you will use to * sign it with your Bitcoin Wallet (Electrum or Bitcoin Core) * This is the first step before submit your Block. * The method return a Promise that will resolve with the message to be signed * @param {*} address

requestMessageOwnershipVerification(address) { return new Promise((resolve) => { let message = `${address}:${new Date().getTime().toString().slice(0,-3)}:starRegistry`; resolve(message); }); }

Blockchain.js * The submitStar(address, message, signature, star) method * will allow users to register a new Block with the star object * into the chain. This method will resolve with the Block added or * reject with an error. * Algorithm steps: * 1. Get the time from the message sent as a parameter example: `parseInt(message.split(':')[1])` * 2. Get the current time: `let currentTime = parseInt(new Date().getTime().toString().slice(0, -3));` * 3. Check if the time elapsed is less than 5 minutes * 4. Veify the message with wallet address and signature: `bitcoinMessage.verify(message, address, signature)` * 5. Create the block and add it to the chain * 6. Resolve with the block added. * @param {*} address * @param {*} message * @param {*} signature * @param {*} star

submitStar(address, message, signature, star) { let self = this; return new Promise(async (resolve, reject) => { let time = parseInt(message.split(':')[1]); let currentTime = parseInt(new Date().getTime().toString().slice(0, -3)); if((time + (5*60*1000)) >= currentTime){ // verify the signature let isValid = bitcoinMessage.verify(message, address, signature); if(isValid){ let block = new BlockClass.Block({owner: address, star: star}); let addedBlock = await self._addBlock(block); resolve(addedBlock); } else { reject('Your signature is not valid'); } } else { reject('You should submit the star before 5 minutes'); } }); }

Block.js validate() method will validate if the block has been tampered or not. * Been tampered means that someone from outside the application tried to change * values in the block data as a consecuence the hash of the block should be different. * Steps: * 1. Return a new promise to allow the method be called asynchronous. * 2. Save the in auxiliary variable the current hash of the block (`this` represent the block object) * 3. Recalculate the hash of the entire block (Use SHA256 from crypto-js library) * 4. Compare if the auxiliary hash value is different from the calculated one. * 5. Resolve true or false depending if it is valid or not. * Note: to access the class values inside a Promise code you need to create an auxiliary value `let self = this;`

validate() { let self = this; return new Promise((resolve, reject) => { let hashAux = self.hash; // Save in auxiliary variable the current block hash self.hash = null; let calculatedHash = SHA256(JSON.stringify(this)).toString(); // Recalculate the hash of the Block if( calculatedHash !== hashAux ){ // Comparing if the hashes changed resolve(false); // Returning the Block is not valid } else { resolve(true); // Returning the Block is valid } }); }

Blockchain.js * This method will return a Promise that will resolve with the list of errors when validating the chain. * Steps to validate: * 1. You should validate each block using `validateBlock` * 2. Each Block should check the with the previousBlockHash

validateChain() { let self = this; let errorLog = []; return new Promise(async (resolve, reject) => { let promises = []; let chainIndex = 0; self.chain.forEach(block => { promises.push(block.validate()); if(block.height > 0) { let previousBlockHash = block.previousBlockHash; let blockHash = chain[chainIndex-1].hash; if(blockHash != previousBlockHash){ errorLog.push(`Error - Block Heigh: ${block.height} - Previous Hash don't match.`); } } chainIndex++; }); Promise.all(promises).then((results) => { chainIndex = 0; results.forEach(valid => { if(!valid){ errorLog.push(`Error - Block Heigh: ${self.chain[chainIndex].height} - Has been Tampered.`); } chainIndex++; }); resolve(errorLog); }).catch((err) => { console.log(err); reject(err)}); }); } }


Related study sets

Practice quiz exam 1 statistics and research

View Set

Interpersonal Communications Chapter 11

View Set

Microbiology Lab [ LAB EXAM 1 ] Review

View Set

MODULE 6: CAPITAL STRUCTURE AND LEVERAGE - Q3

View Set

Regular and Irregular Plural Nouns

View Set

Chapter 9 The Civil War & Reconstruction

View Set